Can we implement deeplinking for a mobile app without having a website or do we have to have a predefined specific website to implemment it?
Deep linking can work without having a specific website. All you need for it to work is add the <intent-filter> ... </intent-filter> tag to your preferred activity via the AndroidManifest.
Then create a unique URI pattern intended to match any HTTP URI such as http://your-app-domain/content or a custom scheme such as your-app://content. Add this scheme to the <data ... /> tag.
Here's what your activity should look like when you're done.
<activity
android:name=".activities.DeepLinkingActivity"
android:label="#string/title_activity_deeplink">
<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="your-app-domain"
android:pathPrefix="/content"
android:scheme="http" />
</intent-filter>
</activity>
Regardless of the URI scheme you choose, you should be able to begin your activity when an intent with the scheme is triggered.
If you are familiar with adb commands, enter this command
adb shell am start -a android.intent.action.VIEW -d "http://your-app-domain/content" com.your-app-package
Further reading https://developers.google.com/app-indexing/android/app
Related
I made changes in Android manifes as suggested here:
https://docs.flutter.dev/development/ui/navigation/deep-linking
So, new metadata and config has been added to MainActivity:
<!-- Deep linking -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<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="http" android:host="flutterbooksample.com" />
<data android:scheme="https" />
</intent-filter>
As a result, when I use adb for testing as they said to do:
adb shell am start -a android.intent.action.VIEW \
-c android.intent.category.BROWSABLE \
-d "http://flutterbooksample.com/book/1"
I am getting what I want:
But if I try to open url http://flutterbooksample.com/book/1 directly in browser on my emulator, nothing happens, browser opens page and theres no prompt to open url in my app.
Do I need to do anything else to make it working?
Short Answer
You can't call the deep link URL from the web browser's search bar. First, you need to create an HTML page. Then you can click the link. It will work.
More details
In my case, I created an HTML file with a deep link and send it to my email.
HTML file
Open my app
AndroidManifest.xml
<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="test"
android:scheme="myapp" />
</intent-filter>
I am attempting to get the Android application chooser to launch when a specific URL is clicked from within a registration e-mail. I have already looked at the below question and several others but I am still having no luck with this.
Launching Android Application from link or email
I have created my intent in the AndroidManifest.xml file as below (I've placed my website address where you see ".website.org"):
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize">
<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="*.website.org"
android:path="/" />
</intent-filter>
</activity>
Is anyone able to assist me with what else I may be missing, as this is currently not launching anything and it's just loading the link directly in the default web browser?
You achieve this by Deep linking in your app.
First of all you need to add intent filters for incoming links.
<action>
Specify the ACTION_VIEW intent action so that the intent filter can be
reached from Google Search.
<data>
Add one or more tags, each of which represents a URI format
that resolves to the activity. At minimum, the tag must include
the android:scheme attribute.
You can add more attributes to further
refine the type of URI that the activity accepts. For example, you
might have multiple activities that accept similar URIs, but which
differ simply based on the path name. In this case, use the
android:path attribute or its pathPattern or pathPrefix variants to
differentiate which activity the system should open for different URI
paths.
<category>
Include the BROWSABLE category. It is required in order for the intent
filter to be accessible from a web browser. Without it, clicking a
link in a browser cannot resolve to your app.
Also include the DEFAULT
category. This allows your app to respond to implicit intents. Without
this, the activity can be started only if the intent specifies your
app component name.
I have used this url for launch my app “http://www.example.com/gizmos”
Look at the my Manifest.xml file,
<activity
android:name="com.example.android.GizmosActivity"
android:label="#string/title_gizmos" >
<intent-filter android:label="#string/filter_view_http_gizmos">
<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://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
</intent-filter>
<intent-filter android:label="#string/filter_view_example_gizmos">
<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 "example://gizmos” -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
And notice that the two intent filters only differ by the <data> element.
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
<data android:scheme="app" android:host="open.my.app" />
</intent-filter>
It might seem as though this supports only https://www.example.com and
app://open.my.app. However, it actually supports those two, plus
these: app://www.example.com and https://open.my.app.
Read data from incoming intents
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
}
Test your deep links
The general syntax for testing an intent filter URI with adb is:
$ adb shell am start
-W -a android.intent.action.VIEW
-d <URI> <PACKAGE>
For example, the command below tries to view a target app activity that is associated with the specified URI.
$ adb shell am start
-W -a android.intent.action.VIEW
-d "example://gizmos" com.example.android
Thanks for your replies. In the end I had to change my intent to the below and it had the desired result. When I click the URL specified in my intent the application chooser pops up allowing me to load the link in my app.
Just as info for anyone struggling as I did, you do not need to read data from incoming intents for the application chooser to launch, all you need is the below in your AndroidManifest file.
<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="http" />
<data android:scheme="https" />
<data android:host=".website.com" />
</intent-filter>
Thanks All.
First of All try to write the whole path for the Url in
android:host"https://www.google.com"
And next please check that you have not opted for default browser for link in android device.
Remove any default for link if any and try again.
Android studio made this task very easy they introduced App Links Assistant in Android Studio 2.3 -. It does every thing for you and test as well.
It can be found in android studio
Tools > App Links Assistant.
useful demo video can be seen at this link.
https://www.youtube.com/watch?v=lpaByLW_ctw
I'm creating a intent-filter in order to filter in my app urls like https://www.hotelsclick.com/?hotel_id=135738
I see in the documentation that I should create an intent filter like
<intent-filter android:label="#string/filter_title_viewgizmos">
<action android:name="android.intent.action.VIEW" />
<!-- Accepts URIs that begin with "http://example.com/gizmos” -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/gizmos" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
This intent-filter should filter URLs like "http://example.com/gizmos?1234, http://example.com/gizmos/1234, http://example.com/gizmos/toys/1234"
That's good but... my URL is different, it's like http://example.com?toys=1234 'cause it's got a named GET parameter just in the home page, which is hotel_id.
How can I filter such URLs? Is there some more parameter to put in the intent-filter definition?
Edit: I put the following intent-filter in my Manifest.xml
<intent-filter android:label="#string/app_name">
<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="hotelsclick.com" />
<data android:scheme="http"
android:host="hotelsclick.com" />
</intent-filter>
and I CAN open the app by providing this ADB command
adb shell am start -a android.intent.action.VIEW -d "http://hotelsclick.com?hotel_id=135738" com.towers.hotelsclick
BUT it doesn't work from the page self-generated with the deep-link tool: https://developers.google.com/app-indexing/webmasters/test?hl=it
I put in the webpage the following URI in the editText: "android-app://com.towers.hotelsclick/hotelsclick.com?hotel_id=135738" and I got this page: https://applinktest.appspot.com/app-link.html?url=android-app%3A%2F%2Fcom.towers.hotelsclick%2Fhotelsclick.com%3Fhotel_id%3D135738
As you can see the link in the page is intent://#Intent;scheme=hotelsclick.com?hotel_id=135738;package=com.towers.hotelsclick;end and I expected this intent-link to be opened by the app itself when clicked on mobile on the same phone I used for the adb command before. But it doesn't work and takes me straight to the google play store, suggesting to open the app from there
So, since I can make the intent-filter work via ADB but not with a proper link, can I say I succeeded or not?
Thank you
The generated link is not valid. It should be
intent://hotelsclick.com?hotel_id=135738#Intent;scheme=http;package=com.towers.hotelsclick;end
instead of
intent://#Intent;scheme=hotelsclick.com?hotel_id=135738;package=com.towers.hotelsclick;end
The closest I could find was this question here. but it doesnt quite cover the problem im having.
I have deep links in my app setup to use /app as the path prefix. The problem I'm having is that links like http://example.com/upgrade are also trying to open in my app even though it doesn't have /app anywhere in the url. I understand you cant exclude urls specified by the prefix, but isn't the whole point of path prefix to include only those urls?
basically I want links like these to deep link:
http://example.com/app/home
http://example.com/app/specials
but not links like these:
http://exaple.com/
http://example.com/login
and here is what I have in my manifest:
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app"/>
Edit 1
also found this link but i dont have any empty prefixes, only ones with just a slash "/"
Edit 2
The url that was triggering it was http://example.com/upgrade.php?app=1&method=1&uid=1, I wasn't sure if app after the ? would also trigger it so I changed the prefix to /application but that also didn't work, its still triggering them.
Edit 3
here are the other deep link data tags in the manifest:
profile activity
<data android:scheme="myapp"
android:host="profile"
android:pathPrefix="/"/>
login/signup activity
<data android:scheme="myapp"
android:host="login"
android:pathPrefix="/signup"/>
main activity
<data android:scheme="myapp"
android:host="main"
android:pathPrefix="/"/>
<data android:scheme="http"
android:host="test.example.com"
android:pathPrefix="/app"/>
<data android:scheme="http"
android:host="live.example.com"
android:pathPrefix="/app"/>
Edit 4
This is getting more and more confusing, if I remove the data tag with myapp as the scheme from the activity (or if i remove the pathPrefix from everything with a prefix of "/") it no longer triggers the deep links from the web urls, even if they have /app in them.
I figured it out, It seems like the data tags sort of bleed into one another, so the prefix of "/" on the data with scheme "example" was also applying to all of the schemes in the other data tags. I just had to use separate Intent filters for my custom scheme deep links and the url deep links like so:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- must start with http://test.example.com/app -->
<!-- http://test.example.com/ won't work since prefix / is in a different intent-filter -->
<data android:scheme="http"
android:host="test.example.com"
android:pathPrefix="/app"/>
<!-- must start with http://live.example.com/app -->
<data android:scheme="http"
android:host="live.example.com"
android:pathPrefix="/app"/>
</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" />
<!-- must start with example://main/ -->
<!-- http://test.example.com/ won't work since http is in a different intent-filter -->
<data android:scheme="example"
android:host="main"
android:pathPrefix="/"/>
</intent-filter>
</activity>
As explained here, your attributes get merged:
Although it's possible to include multiple <data> elements in the same filter, it's important that you create separate filters when your intention is to declare unique URLs (such as a specific combination of scheme and host), because multiple <data> elements in the same intent filter are actually merged together to account for all variations of their combined attributes.
Putting them into separate instances of <intent-filter> therefore fixes your problem.
Running a few tests on my own I think you have created this problem yourself, before continuing to test any more deep links from your app go to
Settings -> Your App Name -> Launch by Default and select Clear defaults
Then navigate back to your app manifest and add the intent filter to your Activity for each url:
In your example you ask for
http://example.com/app/home
http://example.com/app/specials
I am going to assume you have an Activity that would launch each one of these for the URI given above.
for HomeActivity in manifest do:
<activity android:name=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- http://example.com/app/home -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app/home"/>
<!-- https://example.com/app/home -->
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/app/home"/>
<!-- custom url scheme example://app/home -->
<data android:scheme="example"
android:host="app"
android:pathPrefix="/home"/>
</intent-filter>
</activity>
Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/home and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/home From your terminal
then for your SpecialsActivity
<activity android:name=".SpecialsActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- http://example.com/app/specials -->
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="/app/specials"/>
<!-- https://example.com/app/specials -->
<data android:scheme="https"
android:host="example.com"
android:pathPrefix="/app/specials"/>
<!-- custom url scheme example://app/specials -->
<data android:scheme="example"
android:host="app"
android:pathPrefix="/specials"/>
</intent-filter>
</activity>
Test with adb shell am start -W -a android.intent.action.VIEW -d http://example.com/app/specials and adb shell am start -W -a android.intent.action.VIEW -d example.com/app/specials From your terminal
this is pretty much how it works, if you set your app to handle a http://example.com/ url and select choose by default then, well its going to try to open http://example.com/{anything} using your app
So in short, when you specify your pathPrefix, make sure you include what you really want to intercept and don't choose your app by default if you test a link that shouldn't open your app, just adjust your pathPrefix so it won't be triggered by your app.
For example the URLS above won't open
http://example.com/app
because we haven't defined a <data /> tag to handle this.
UPDATE
And to add straight from the docs when using \ or *:
Because '\' is used as an escape character when the string is read from XML (before it is parsed as a pattern), you will need to double-escape: For example, a literal '*' would be written as '\\*' and a literal '\' would be written as '\\\\'. This is basically the same as what you would need to write if constructing the string in Java code.
Good luck and happy coding!
I am trying to add deep linking to my app. I have added 2 intent filters to one of my activities, one filter for the "http" scheme, and another for my custom scheme (I'm using "example"). I have added one intent filter per scheme, based on the info in this SO (Deep-linking intent does not work), so that I can handle both example://test and http://www.example.com/test type of links.
Here is my XML:
<activity
android:name="com.myapp.myapp.SplashActivity"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Holo.Light.NoActionBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="Intent Filter label">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- Accepts URIs that begin with "http://www.example.com/test2” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/test2" />
</intent-filter>
<intent-filter android:label="Intent Filter label">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
<!-- Accepts URIs that begin with "example://test2” -->
<data android:scheme="example"
android:host="test2" />
</intent-filter>
</activity>
They are loading correctly when I test in ADB:
adb shell am start -W -a android.intent.action.MAIN -d "example://test2" com.myapp.myapp
returns
Starting: Intent { act=android.intent.action.MAIN dat=example://test2 pkg=com.myapp.myapp }
Status: ok
Activity: com.myapp.myapp/com.app.myapp.SplashActivity
ThisTime: 357
TotalTime: 357
Complete
However, I get absolutely nothing in a browser. When I try this in a browser:
"example://test2" in FF I get "couldn't find an app to open this link" and in Chrome and the Native Browser, it opens up new Google search for "example://test2".
When I try the other style: "http://www.example.com/test2" it just tries to navigate to that web page in all 3 browsers.
I am deploying the app to my phone from Android Studio. I have also tried by generating a debug APK, sending it to my phone, and installing. Same result for both.
What am I doing wrong? I've followed the guide (https://developer.android.com/training/app-indexing/deep-linking.html) to the letter as far as I can tell. Does my app need to be in the store for the deep linking to work?
Ughh, my action was MAIN when it should have been VIEW...
<intent-filter>
<action android:name="android.intent.action.MAIN" />
...
<intent-filter>
<action android:name="android.intent.action.VIEW" />
Your implementation seems to be correct and also, if you're testing your app in your device, it does not need to be available on Playstore.
Have you tried testing through a QR code? As is demonstrated in Google documents - https://developers.google.com/app-indexing/android/test
Hope this helps.
The scheme (and probably host) have to be in all lower case.
From the uni_link package i copied the deep link 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" />
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
<data
<!-- THIS HAS TO BE IN ALL LOWER CASE -->
android:scheme="[YOUR_SCHEME]"
<!-- android:scheme="[your_scheme]" -->
android:host="[YOUR_HOST]" />
</intent-filter>
and pasted in my package name com.myPackage.app as the scheme. For the host I put localhost.
Changing the scheme to all lower case com.mypackage.app allowed the deep link to work.
You can use this site to test the deep link without using adb.
PS: This is not true for iOS where the CFBundleURLName and CFBundleURLSchemes can contain uppercase letters.