I would like to be able to display my own calendar events, given an Android intent and a date to display. I believe that the intent to do so looks like this:
Intent { act=android.intent.action.VIEW act=content://com.android.calendar/time/1409565898789 }
And I have set up the Activity to handle this intent with an intent filter specified thus in my AndroidManifest.xml:
<activity
android:name=".MyActivity"
android:label="#string/title_activity_custom"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<!-- etc. -->
</activity>
In order to test this code, I load my application onto my test device and issue an intent using this command:
adb shell am start -a android.intent.action.VIEW -d content://com.android.calendar/time/1410665898789
But when I do so, the stock Android calendar is launched. I am never given an opportunity to view this time in another application. I think perhaps the Android system doesn't even recognize my Activity as a candidate for receiving this Intent.
I am not sure what I'm doing wrong and none of my searches have turned up the answer I'm seeking. Does anyone know what I'm missing?
You need to add the scheme, MIME type, and perhaps the host to your <intent-filter>. Now, I do not know what the MIME type is precisely, so I am guessing that the following <intent-filter> from the AOSP Calendar app is what you are seeking:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="time/epoch" />
<data android:host="com.android.calendar" />
<data android:scheme="content"/>
</intent-filter>
Your current <intent-filter> will match nothing, unless some app has a bug and tries starting an ACTION_VIEW activity with no Uri.
Related
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 developing an Android app that needs a deep link with an NFC tag.
Here you can see my intent filter for the activity:
<activity
android:name=".ui.schedule.ScheduleActivity"
android:parentActivityName=".ui.home.HomeActivity">
<intent-filter android:label="testDeepLink">
<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="www.testdeeplink.com"
android:pathPrefix="/schedule"/>
</intent-filter>
</activity>
Now when I start this command in adb the application starts with the correct activity (ScheduleActivity):
adb shell am start -W -a android.intent.action.VIEW -d "http://www.testdeeplink.com/schedule?stop_id=1" com.exmemple.android
But when I encode the URL on an NFC tag, scanning that tag just starts the web browser of my phone. What am I missing to start the activity with the NFC tag?
URL encoded on the tag: "http://www.testdeeplink.com/schedule?stop_id=1"
You are missing to put an NFC intent filter in your manifest. URLs on NFC tags won't trigger an intent action VIEW. Instead, they will be sent to activities with the intent action NDEF_DISCOVERED. Consequently, you can receive such an NFC intent by putting an additional intent filter for action NDEF_DISCOVERED in your manifest:
<activity
android:name=".ui.schedule.ScheduleActivity"
android:parentActivityName=".ui.home.HomeActivity">
<intent-filter android:label="testDeepLink">
<action android:name="android.intent.action.VIEW" />
...
</intent-filter>
<intent-filter android:label="testDeepLinkNFC">
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"
android:host="www.testdeeplink.com"
android:pathPrefix="/schedule" />
</intent-filter>
Note that there seem to be some (unconfirmed?) issues with some devices running Android 6.0+ where the browser seems to hijack URLs from NFC tags despite correct NDEF intent filters. I did not experience this myself so far so I could not further investigate this though.
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
I wanted to register my launcher activity so it could be started by both clicking on icon and opening link with a custom scheme. I managed to make it work but am questioning is this correct way. This is the relevant part of my manifest:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
<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="my.sheme" />
</intent-filter>
This does work but I was wondering should I register both actions under same intent filter. I tried just moving tags from second filter to the first one but then my activity doesn't show icon on install. Is it possible to do it this way and I just made some small syntax error(or broke some undocumented order of declaration rule) or is my thinking completely wrong on this and there are deeper reasons why this doesn't work?
NOTE:I do set android:exported="true"but android.intent.action.MAIN works even without it because it becomes exported anyway if you use action.MAIN
As the Android documentation states:
When you want to handle multiple kinds of intents, but only in specific combinations of action, data, and category type, then you need to create multiple intent filters.
Otherwise you can group them into one intent-filter.
I am trying to read (first time - new to me) a gmail attachment (.gcsb extension) in my app. The intent filter looks like this:
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:pathPattern="*.gcsb"></data>
<data android:mimeType="application/*"></data>
</intent-filter>
and that appears to get the 'download' and 'preview' buttons to appear next to the attachment in gmail (without that filter, the buttons do not appear).
In the activity (onCreate() / onRestart()) I do:
....
Intent intent = getIntent();
if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
// Deal with the file from gmail here
}
....
to check if it is gmail that has caused this to start the activity or not.
However intent.getAction() always resolves to android.intent.action.MAIN, so it never does anything. There is another intent filter in the activity:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
being for the app launch, but I don't understand why I never see the android.intent.action.VIEW from gmail?
The answer appears to be that the activity was set to be 'single instance' for various reasons. This means that whilst it is brought to the foreground again, it comes back with the intent it was originally started with, not the one created by gmail.
Removing the 'single instance' attribute allowed the correct intent to be used.