Launch Activity From URL - android

I am trying to have my application launch when the user browses to a certain url. I have found a few examples and they all have the same things in the manifests but it's not working for me. I have put the intent-filter under an Activity as well as a Receiver.
Here is my manifest snippet:
<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:host="www.urbandictionary.com" android:scheme="http"></data>
</intent-filter>
When under the Activity, I tried using onNewIntent and when it was under a Receiver, I tried using onReceiveIntent, both with a simple Log.i call to see if it fired or not. I am not having much luck.

I use this in my manifest.xml file:
<activity android:name=".SomeName">
<intent-filter>
<category android:name="android.intent.category.ALTERNATIVE" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="google.com" android:scheme="http" />
</intent-filter>
</activity>
This will start activity SomeName. I don't use www in the android:host part maybe that will make a difference.
When the activity starts you can get the data that's behind the .com using (for example):
Uri data = getIntent().getData();
if(data != null && data.getPathSegments().size() >= 2){
List<String> params = data.getPathSegments();
String somestuff = params.get(0);
}
Edit: If you wan't to be able to check the host from within the activity, use this method:
data.getHost();

Related

Including two intent-filters, sharing same activity, action, category and mimeType

I'd like to add a share functionality to share photos with my app,
the app has two main functionalities, each uses photos as the main input data from the user.
So I need to have two share buttons for the two functionalities. I added this in the application tag in the AndroidManifest.xml:
<activity android:name="MainActivity">
<intent-filter android:label="#string/ENCODE">
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter android:label="#string/DECODE">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity >
but only the first intent filter is applied.
but when I specified another activity for the second filter, it worked:
<activity android:name="MainActivity" android:label="#string/ENCODE">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity >
<activity android:name="com.company.myapp.DecodeActivity" android:label="#string/DECODE">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity >
but I had to create DecodeActivity and copy the setup code from the MainActivity, this for example caused problems like they share some resources (photo picker) that gets ambiguous between activities and navigate from the DecodeActivity to the MainActivity, because it initially uses the MainActivity.
Here I'm resolving the incoming intent:
if (Intent.ActionSend.Equals(Intent.Action) && Intent.Type != null && Intent.Type.StartsWith("image/"))
{
await ImageDispatcher.HandleSendImage(ContentResolver, Intent, "Encode");
}
The two intent filters differ only by the label, which does not affect the function of the filter in any way.
I think you should have two activities (one for each operation), and both should have the same base class. Put the operation-specific code in the operation-specific activities.
Alternatively, you may ask the user what to do with the image.

How to open specific app's specific activity clicking on an external link?

I am developing an android app, in which user must need to login first to use it's features. So as usual user must need to login using provided user credential.
But I don't want user always enter username and password again and again, so that I am just sharing a URL with user and if user click on shared link from anywhere in phone (via mail, or WhatsApp, or Facebook, etc.) phone must prompt to choose my app and app should automatically extract the URL and directly redirect the app to my Home Screen by hitting the login api if username and password are correct.
The shared url will be look like this - http://www.myurl.com/sso?username=Scb56745&password=!l0Aeu0yQazxssx
For now I have managed to prompt the dialog using this code in my AndroidManifest file -
<activity
android:name="com.my.par.activities.UserActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
<intent-filter android:autoVerify="true" tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.myurl.com"
android:path="/sso"
android:scheme="http" />
<data
android:host="www.yoururl.com"
android:path="/sso1"
android:scheme="https" />
</intent-filter>
</activity>
I am getting this clicked URL link in my UserAcitivity's on getIntent() method, like this -
Uri uri = getIntent().getData();
String path = uri.getPath();
So my real question is how to extract the username and password separately and so that I can call my login api by sending this username and password from this url (for ex. http://www.myurl.com/sso?username=Scb56745&password=!l0Aeu0yQazxssx). - Done
And how can I put a dynamic URL or host name, path and scheme in AndroidMenifest file? - Done
How can we force our app to always directly open the app,(don't need to show the chooser dialog) because no use of it even user click on browser nothing gonna happen.
Happy coding :-)
Karzel is also right but it's written in Kotlin, I believe you are expecting the solution for Java I'll answer the same in Java
Uri uri = getIntent().getData();
String strUsername = "", strPassword = "";
if (uri != null) {
strUsername = uri.getQueryParameter("username");
strPassword = uri.getQueryParameter("password");
}
else {
// Your app will pop up even if http://www.myurl.com/sso is clicked, so better to handle null uri
}
To answer your next part about dynamic URL, you can have multiple intent-filters for that purpose
<activity
android:name="com.my.par.activities.UserActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
<intent-filter android:autoVerify="true" tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.myurl.com"
android:path="/sso"
android:scheme="http" />
</intent-filter>
<intent-filter android:autoVerify="true" tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.myurl.com"
android:path="/sso"
android:scheme="https" />
</intent-filter>
<intent-filter android:autoVerify="true" tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.myurl.com"
android:path="/debug"
android:scheme="http" />
</intent-filter>
</activity>
and so on.
To open your app directly by clicking the link and not show a chooser dialog you'll have to use a custom URI, for example:
syn3sthete://myurl.com/sso?username=Scb56745&password=!l0Aeu0yQazxssx
You can change syn3sthete to any custom value you want.
Don't forget to add an intent-filter for your custom URI.
<intent-filter android:autoVerify="true" tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="myurl.com"
android:path="/sso"
android:scheme="syn3sthete" />
</intent-filter>
Try using code like this :
fun getUsernameFromUrl(url: String): String? {
return Uri.parse(url).getQueryParameter("username")
}
fun getPasswordFromUrl(url: String): String? {
return Uri.parse(url).getQueryParameter("password")
}
And call it
val username = getUsernameFromUrl(path)
etc.
UPDATE:
The only "dynamic" way of adding URL I know is using something like this :
https://developer.android.com/studio/build/manifest-build-variables
you can change this URL depending on your Build Variant.
As is said here :
https://stackoverflow.com/a/43339476/8713068
you cannot update Android Manifest directly from code

Allow other app to start my Activity

I have used this example so that other applications can call my activity to receive data from them.
Specifically, I want when uploading an image from a browser my application can supply that image.
In the following image can see that case. A list of applications that provide images when the user clicks upload file:
I used this code that is copied from the link I added to the start.
<activity
android:name=".LoginActivity"
android:label="#string/title_activity_login">
<!-- filter for sending text or images; accepts SEND action and text or image data -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
I can not get my app to appear in the apps list shown in the photo.
Also I test this, as #Avi suggests:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.APP_BROWSER" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
</intent-filter>
Getting the same results
Note: I am using the chrome browser in Android
Change below line
<action android:name="android.intent.action.SEND" />
to
<action android:name="android.intent.action.VIEW" />
I got my app to appear in the browser when uploading an image with the following code.
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.media.action.STILL_IMAGE_CAMERA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Try this-
Manifest file:
<activity
android:name=".activities.HomeActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Your MainActivity file:
val data: Uri? = intent?.data
// Figure out what to do based on the intent type
if (intent?.type?.startsWith("image/") == true) {
// This handles the intents with image data or of any other type based on your specified condition.
} else if (intent?.type == "text/plain") {
// This handle the intents with text or based on your conditions
//Use any popup like toast, snackbar, dialog, etc of your preference.
}
And also please do check whether you have mentioned your action as VIEW or SEND.
If its a VIEW it wont reflect in your result but if its SEND then it will work.
Check for this if in any of the file you have mentioned this-
val sendIntent = Intent(Intent.ACTION_SEND) //Replace to SEND if you have used ACTION_VIEW
sendIntent.type = "image/*"
val title = context?.resources?.getString(R.string.chooser_text)
if (context?.packageManager != null) {
context?.startActivity(Intent.createChooser(sendIntent, title))
}
And if you want to fetch the result of your action the insert this too...
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
setResult(Activity.RESULT_OK, result)
}
finish()
For better understanding of this flow, refer this -> https://developer.android.com/training/basics/intents/filters

Deeplinking in Android app

I am trying to enable deeplinking in my app. Here is the code I am running in AndroidManifest to achieve it:
<activity
android:name=".ui.WalletActivity"
android:label="#string/title_activity_wallet">
<intent-filter android:label="#string/title_activity_link_wallet" >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="wallet"
/>
</intent-filter>
</activity>
Is there anything else I need to do in order to make tapping on myapp://wallet to open WalletActivity of my app?
In my app, this works fine:
<activity
android:name=".ui.WalletActivity"
android:label="#string/title_activity_wallet">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<intent-filter>
<data android:scheme="myapp" android:host="wallet" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
I also have extra parameters (myapp://wallet?id=42), which I parse like this:
Intent intent = getIntent();
String providerUrl = intent.getData().toString();
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
sanitizer.setAllowUnregisteredParamaters(true);
sanitizer.parseUrl(providerUrl);
String id = sanitizer.getValue("id");
(You can read about UrlQuerySanitizer here)
To test, I'd suggest to send the myapp://wallet link to yourself via email, for example :-) (or adb, as mentioned in the comments)
To test and make sure that your intent is working, you can use adb command as suggested in the deep linking docs
To pass parameters in your uri, simply add them as a normal query parameter (i.e. example://gizmos/path?key=value, then retrieve them by parsing the intent data like this:
Uri uri = getIntent().getData();
String value = uri.getQueryParameter("key");
Make sure you check for nulls etc.

Implement deep linking in android from single activity

Although I have gone through related document on google for app indexing
https://developers.google.com/app-indexing/webmasters/details
But still have confusion that If I want to receive incoming data on launcher activity and from there If can take control and start relevant activity/fragment depending on some internal parsing over incoming url.
You have to declare the action, category and data in a separate <intent-filter> tag, not in the same one with launcher specs.
<activity>
<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:host="your.domain.com"
android:scheme="http" />
</intent-filter>
</activity>
Not quite sure if I understood what your asking, so please correct me if I'm not answering your question.
Only the activity (or activities) that you put the intent filter in will catch an intent and start. Therefore, if you only put the intent filter in one activity, only that activity will start, and not any of the others. You can put multiple intent filters in the same activity to catch multiple intents. You can also use the path segment of the url to send more information to your activity, and parse it in your activity.
Put the following in your manifest under the activity you want to launch (the path is optional):
<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="http" android:host="www.yourwebsite.com" />
</intent-filter>
Use a url like http://www.yourwebsite.com/yourstring to open the app.
Then use getIntent().getData() to get the uri that started the activity. You can then parse the uri to get yourstring.
Add Following Intent filter to Activity you want to open via Deep linking in Manifest.
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Then As per Intent data you get in Activity you can perform your action, too.

Categories

Resources