I have an Android/Kotlin application and I would like to configure deep links for certain pages to open inside my application (to look native).
At the moment, I have intent filters that redirect the user to an activity with WebView in which I open the desired url:
<activity android:name=".activity.WebViewActivity">
<intent-filter android:label="Futurity">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="api.example.com"
android:pathPrefix="/auth/confirm"
android:scheme="https" />
</intent-filter>
</activity>
class WebViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web_view)
val data = intent.data
// construct url
val url = if (intent.data != null ) {
"https://" + data.host + data.path + "?" + data.query
}
appWebView.webViewClient = WebViewClient()
appWebView.loadUrl(url)
}
}
This works fine, but I would like to use Chrome custom tabs instead for security reasons.
However, when I try to configure the custom tab instead of WebView, I am getting an infinite loop of redirects between the page (launched in the chrome tab) and the intent filter which immediately redirects user back to the activity:
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));
How can I achieve the same behavior as with webviews but without modifying the url? Is it even doable?
I did some digging and found out that you should search for packages that support the "warming services". If a package is returned then you can assign the package name to the Intent. Google has a GitHub repo with some helper classes. The one in question is CustomTabHelper#getPackageNameToUse().
So in your case:
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
String packageName = CustomTabsHelper.getPackageNameToUse(getContext());
if (packageName != null) {
customTabsIntent.intent.setPackage(packageName);
}
customTabsIntent.launchUrl(this, Uri.parse(url));
If a package is not found then you'll want to have some fallback code else the infinite loop will keep happening.
Related
I've tried to open my app directly, without opening google play store or browser, when user tap on the link.
I've tried this code:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<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="fptest"
android:host="forgot"
android:pathPrefix="/"/>
</intent-filter>
</activity>
I'm using link as follows
<a href="intent://TestApplication#Intent;scheme=fptest;package=com.example.testapplication;end">
Open App
</a>
where ,
TestApplication -- my app name
package -- com.example.testapplication
But it always open Google Play or a Browser , not my app.
I want to open my app from a link eg : fptest://forgot . I dont want to use http as scheme
You can achieve this by the below code. You don't need to change anything if you are opening your own app. However, if you are willing to open a different app, then just change getPackageName with that specific one.
#SuppressLint("WrongConstant")
public void OpentheApp()
{
Intent localIntent = new Intent("android.intent.action.VIEW", Uri.parse("market://details?id=" + getPackageName()));
localIntent.addFlags(1208483840);
try
{
startActivity(localIntent);
}
catch (Exception localException)
{
startActivity(new Intent("android.intent.action.VIEW", Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())));
}
}
If you want to open it by webview. Then Follow this:
Declare these two on the Activity.
String market_url = "market://details?id=package_name";
String website_url = "https://play.google.com/store/apps/details?id=package_name";
Inside OnCreate:
WebView webview = (WebView) findViewById(R.id.webview);
webview.loadUrl("file:///android_asset/index.html"); // path to html
webview.setWebViewClient(new Callback());
private class Callback extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.equals(website_url)) {
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(market_url));
startActivity(intent);
} catch (ActivityNotFoundException e) {
}
}
return (false);
}
}
index.html
App link
It will open the app in the play store.
<data
android:host="www.yourdomain.com"
android:pathPrefix="/api/forgot"
android:scheme="https"
</data>
Then handle the data in onCreate() and onNewIntent().
Your host should be the complete domain of the incoming url.
PathPrefix should be the path segments
And scheme should could any of http/https/etc
You can use a URL like:-
https://www.yourdomain.com/api/forgot/abc.php
Add this as your link
<a href="intent://forgot#Intent;scheme=fptest;package=com.example.testapplication;end">
Open App
</a>
Note: I replaced TestApplication with forgot you need to use host after the intent://
I am trying to integrate FIT BIT login in my android application .
but i am not getting any call back in my application when the login is successful
I am using this reference fit bit link
As in the document we cannot use web view so i used Chrome Custom Tabs .
this is my redirect URL = "http://52.9.44.227:3000/feed"
which is returned from the url
this is my manifest for getting call back
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data
android:host="52.9.44.227:3000"
android:pathPrefix="/feed"
android:scheme="http" />
</intent-filter>
</activity>
This is my java code to launch the web URL by fit bit.
void launchTab(final Context context, final Uri uri){
final CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
#Override
public void onCustomTabsServiceConnected(ComponentName componentName, CustomTabsClient client) {
final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
final CustomTabsIntent intent = builder.build();
client.warmup(0L); // This prevents backgrounding after redirection
intent.launchUrl(context, uri);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
CustomTabsClient.bindCustomTabsService(context, "com.android.chrome", connection);
}
this is the URL is trying hit for fit bit login
fit bit login link
I made a android webview app for our website. Now i want to add deep links to the app, like when somebody clicks a link of our website, you can open it with the webview app instead of chrome web browser. I added these to my manifest:
<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="www.example.com" />
Now it opens the webview app when I click a link which is related to us, but it doesnt open the right page, its just starting the app again. But I want to open the directly the right page inside the webview app.
EDIT:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//added
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
But it seems that the variables action and data are not used.
I load the webview like this (for three languages).
//loads the main website
//sets the matching language
web2.clearCache(true);
String loc = Locale.getDefault().toString();
if (loc.startsWith("de")) {
web2.loadUrl("https://www.example.de");
} else if (loc.startsWith("nl")) {
web2.loadUrl("https://www.example.nl");
} else {
web2.loadUrl("https://www.example.com");
}
You must use the intent data that your activity receives when its opened via deep link. Example in Kotlin:
class WebViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_webview)
val uri = intent.data
webView.loadUrl(uri.toString())
}
Now I did it like this. That is the solution.
Intent intent = getIntent();
Uri data = intent.getData();
String loc = Locale.getDefault().toString();
if (data==null && loc.startsWith("de")) {
web2.loadUrl("https://www.example.de");
} else if (data==null && loc.startsWith("nl")) {
web2.loadUrl("https://www.example.nl");
} else if (data==null && !loc.startsWith("de") && !loc.startsWith("nl")){
web2.loadUrl("https://www.example.com");
} else {
web2.loadUrl(data.toString());
}
I'm working with the instagram API and I don't understand what I should put in for the redirect api. At the moment I simply put in https://127.0.0.1
But I dont really understand. Also, once I get the allow/cancel screen and I press allow it gives me an error saying that I cant go to that address but I can also see the authorization code appended on to the address. So how can i redirect back from my redirect uri? How can I tell android that after user clicks allow to come back into the app use the code for further authentication?
Im sure you will say something like make my own custom scheme/ intent filters etc but please be a little more supportive im new and I dont understand and I did do research on them.
My on resume method is below
#Override
protected void onResume() {
super.onResume();
// the intent filter defined in AndroidManifest will handle the return from ACTION_VIEW intent
Uri uri = getIntent().getData();
if (uri != null && uri.toString().startsWith(redirectUri)) {
// use the parameter your API exposes for the code (mostly it's "code")
String code = uri.getQueryParameter("code");
if (code != null) {
// get access token
LoginService loginService =
ServiceGenerator.createService(LoginService.class, clientId, clientSecret);
AccessToken accessToken = loginService.getAccessToken(code, "authorization_code");
} else if (uri.getQueryParameter("error") != null) {
// show an error message here
}
}
}
This is my manifest snippet dealing with intent filters:
<activity
android:name=".LoginActivity"
android:label="#string/title_activity_login" >
<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="redirecturi"
android:scheme="your" />
</intent-filter>
</activity>
You have to setup an event listener on the browser view and check for code in URL param if the URL is equal to the redirect_uri, and then make POST request to the auth URL using the code and client_secret as documented in Instagram authentication
something like this:
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
String code = url.getQueryParameter("code");
// ...
}
});
I have a specific URL that I want redirected to a specific activity in my app from a webview with an intent filter. How to implement my very own URI scheme on Android described how to do this for a browser page, but this same intent filter doesn't work when that URL is accessed through the webview. Is there anything else that needs to be added to this intent filter to catch these webview links?
<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="myurl.com/stuff" android:scheme="http"></data>
</intent-filter>`
I have not got intent filters and webviews to work together just with declaring the intent on the manifest and I think they are not supposed to. (I wonder why...) I think the way to do it is catching urls when you are trying to open them in the webview and creating an intent then.
Then, for an activity register as follows in the manifest:
<activity android:name=".PretendChat">
<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="chat" ></data>
<data android:scheme="testing"></data>
<data android:pathPattern=".*"></data>
</intent-filter>
</activity>
You would expect the activity PretendChat opens when you click on a link like the following: "testing://chat" inside the webview. In order for that to happen you
would need the following code on the webview client you are using on the webview. Assume that the activity that starts the webview is called WebviewActivity.
private class TestWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
WebviewActivity.this.startActivity(intent);
} catch(ActivityNotFoundException e) {
Log.e(LOGTAG,"Could not load url"+url);
}
return super.shouldOverrideUrlLoading(view, url);
}
}
The only way I got it to work was to use a dummy file link and loading the URL with loadDataWithBaseURL and using relative links in the data. The latest WebView only seems to accept valid links, and I couldn't get it to work with custom intents for Activities.
If I tried a different scheme, such as "my-app" instead of "file", the url in shouldOverrideUrlLoading would come up as "about:blank".
I also wanted to pass parameters to the activity to be opened in Bundle.
webView.loadDataWithBaseURL("file:///android_asset", w.Definition, "text/html", "utf-8", null);
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("file")) {
Intent intent = new Intent(DictWordActivity.this, DictWordActivity.class);
intent.putExtra("word", Uri.parse(url).getLastPathSegment());
startActivity(intent);
return true;
} else
return false;
}
});
I created my relative links like this:
"" + word + "");
If anyone has a better solution I would like to know.