How to handle ports in URI.Builder class in Android - android

When testing my android app in development environment, I want to connect to a server running on port 9000. But when I supply the port to Builder.authority("localhost:9000"), it does not work. On the other hand if I create the same URL by hand like new URL("localhost:9000"), it works fine.
What is the alternative?

Uri.Builder will encode your URL so that ':' is replaced by %3 .
To prevent encoding use the encoded versions of builder functions:
String host = "localhost:9000";
Uri.Builder builder = new Uri.Builder();
builder.encodedAuthority(host);

Found the solution at http://twigstechtips.blogspot.in/2011/01/android-create-url-using.html. Quoting:
Uri.Builder b = Uri.parse("http://www.yoursite.com:12345").buildUpon();
b.path("/path/to/something/");
b.appendQueryParameter("arg1", String.valueOf(42));
if (username != "") {
b.appendQueryParameter("username", username);
}
String url = b.build().toString();

Related

How to make android.net.Uri encode & between query parameters to %26

I have a Android app that needs to launch a web brower with a URL containing a query string. I build my Uri like this:
Uri uri = builder.scheme("https")
.authority("ids.example.com")
.appendPath("account")
.appendPath("login")
.appendQueryParameter("client_id", "seglaren")
.appendQueryParameter("scope", "openid email name")
.build();
and pass it to the browser using:
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
This launches the browser with the following URL:
https://ids.example.com/account/login?client_id=seglaren&scope=openid%20email%20name
The problem here is that the server I am calling does not accept this URL: it requires the separator between the query parameters to be encoded to "%26" instead of just "&". So it would need to be:
https://ids.example.com/account/login?client_id=seglaren%26scope=openid%20email%20name
How do I fix this?
Instead of .appendQueryParameter() you can use .encodedQuery().
encodedQuery() will be treated as if it is already encoded, thus not encoding it again. So you may insert your own string as you wish like in the example below.
String params = "client_id=seglaren%26scope=openid%20email%20name";
Uri uri = new Uri.Builder().scheme("https")
.authority("ids.artdatabanken.se")
.appendPath("account")
.appendPath("login")
.encodedQuery(params)
.build();
You may use string concatenation or a StringBuilder to make the String params dynamic if you don't want to keep it hardcoded.
Result
"https://ids.artdatabanken.se/account/login?client_id=seglaren%26scope=openid%20email%20name"
Note that androids Uri.Builder is doing the correct thing by adding &to the parameter. So the API you're using probably has a bug if it requires %26.

How to add a protocol to a URL if it does not exist? (in an Android app)

I am working on an app that gets a URL link from the user via edit text widget. How can I check if a given URL has a protocol? And if it doesn't, how can I add the correct protocol for the specific URL?
For example if the user entered: google.com
how can I make it become: https://google.com
The main problem is knowing the correct URL protocol for a given address (is it http/https/ftp? and so on).
You can use String.startsWith() to check if the url String starts with http:// or not
public String valid_url(final String url)
{
if (!url.startsWith("http://") && !url.startsWith("https://"))
{
return "http://" + url;
}
return url;
}
first check if url has protocol using .contains() method
and get protocol using .indexof() and .substring() method
string url = editText.getText().toString();
string protocol;
if(url.contains("://")){
//url has a protocol
int index = url.indexof("://");
//get protocol
protocol = url.substring(0,index-1);
}else{
//url does not have a protocal
// add your protocol to begining of the url
}
You can use android web kit URLUTIL class
package android.webkit;
URLUtil.guessUrl("your web address/String")
example scenarios:
www.testurl.com
testurl.com
testurl
result:
http://www.testurl.com/
Just compare the your output string with .contains() property
String value = editText.getText().toString();
if(!value.contains("https://")) {
// add https:// to ur string
}else {
// No need to add
}
This solution worked for me:
if(!url.startsWith("www.")&& !url.startsWith("http://") && !url.startsWith("https://")){
url = "www."+url;
}
if(!url.startsWith("http://") && !url.startsWith("https://")){
url = "http://"+url;
}
Hope this will help you.
As already adviced use the URL class of the SDK.
Here an example:
var urlWithScheme = new URL("https://www.google.com");
var urlWithoutScheme = new URL("www.google.com");
if (urlWithScheme.getProtocol() != null && urlWithScheme.getProtocol().length() > 0) {
System.out.println("Given URL includes scheme: " + urlWithScheme.getProtocol());
}
if (urlWithoutScheme.getProtocol() != null && urlWithoutScheme.getProtocol().length() > 0) {
System.out.println("Given URL includes scheme: " + urlWithoutScheme.getProtocol());
} else {
System.out.println("Url has no Protocol and you can't guess it by the domain name, because under this name all possible services can exist!");
}
If the given URL has not protocoll you can't guess it. Because under a domain name there can exist any protocol specific service in parrallel.
I would narrow it down to only support http and https. For this you could write a test like connect to https url, if success use it, because https is prefered. If you get redirect or not connection try http ;)

Can we post/send data from Windows Forms Application to Android application?

I have my Windows Forms Application in c# 4.0, I wanted to post/send data to an android application. It need to triggered from Windows Forms.
Any one can suggest me the possible ways to do this?
Thanks & Regards.
Use the WebClient class. Depending on the "payload", you can use of of the UploadXXX methods.
For example:
string URL = "..."; //Your url here
WebClient webClient = new WebClient();
NameValueCollection formData = new NameValueCollection();
formData["Username"] = "myusername";
formData["Password"] = "mypassword";
byte[] responseBytes = webClient.UploadValues(URL, "POST", formData);
string Result = Encoding.UTF8.GetString(responseBytes);
Cheers

Use URI builder in Android or create URL with variables

I'm developing an Android app. I need to build a URI for my app to make an API request. Unless there's another way to put a variable in a URI, this is the easiest way I've found. I found that you need to use Uri.Builder, but I'm not quite sure how to. My url is:
http://lapi.transitchicago.com/api/1.0/ttarrivals.aspx?key=[redacted]&mapid=value
My scheme is http, authority is lapi.transitchicago.com, path is /api/1.0, path segment(s) is ttarrivals.aspx, and query string is key=[redacted]&mapid=value.
My code is below:
Intent intent = getIntent();
String value = intent.getExtras().getString("value");
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority("www.lapi.transitchicago.com")
.appendPath("api")
.appendPath("1.0")
.appendPath("ttarrivals.aspx")
.appendQueryParameter("key", "[redacted]")
.appendQueryParameter("mapid", value);
I understand that I can do URI.add, but how do I integrate it into the Uri.Builder? Should I add everything like URI.add(scheme), URI.add(authority) and so on? Or is that not the way to do it? Also, is there any other easier way to add a variable to a URI/URL?
Let's say that I want to create the following URL:
https://www.myawesomesite.com/turtles/types?type=1&sort=relevance#section-name
To build this with the Uri.Builder I would do the following.
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("www.myawesomesite.com")
.appendPath("turtles")
.appendPath("types")
.appendQueryParameter("type", "1")
.appendQueryParameter("sort", "relevance")
.fragment("section-name");
String myUrl = builder.build().toString();
There is another way of using Uri and we can achieve the same goal
http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7
To build the Uri you can use this:
final String FORECAST_BASE_URL =
"http://api.example.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
You can declare all this the above way or even inside the Uri.parse() and appendQueryParameter()
Uri builtUri = Uri.parse(FORECAST_BASE_URL)
.buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, "json")
.appendQueryParameter(UNITS_PARAM, "metric")
.appendQueryParameter(DAYS_PARAM, Integer.toString(7))
.build();
At last
URL url = new URL(builtUri.toString());
Source: Udacity Android course / Sunshine app
Excellent answer from above turned into a simple utility method.
private Uri buildURI(String url, Map<String, String> params) {
// build url with parameters.
Uri.Builder builder = Uri.parse(url).buildUpon();
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.appendQueryParameter(entry.getKey(), entry.getValue());
}
return builder.build();
}
here is a good way to explain it:
there are two forms of the URI
1 - Builder(ready to be modified, not ready to be used)
2 - Built(not ready to be modified, ready to be used )
You can create a builder by
Uri.Builder builder = new Uri.Builder();
this gonna return a Builder ready to be modified like this:-
builder.scheme("https");
builder.authority("api.github.com");
builder.appendPath("search");
builder.appendPath("repositories");
builder.appendQueryParameter(PARAMETER_QUERY,parameterValue);
but to use it you have to build it first
retrun builder.build();
or however you gonna use it.
and then you have built that is already built for you, ready to use but cannot be modified.
Uri built = Uri.parse("your URI goes here");
this is ready to use but if you want to modify it you need to buildUpon()
Uri built = Uri.parse("Your URI goes here")
.buildUpon(); //now it's ready to be modified
.buildUpon()
.appendQueryParameter(QUERY_PARAMATER, parameterValue)
//any modification you want to make goes here
.build(); // you have to build it back cause you are storing it
// as Uri not Uri.builder
now every time you want to modify it you need to buildUpon() and in the end build().
so Uri.Builder is a Builder type that store a Builder in it.
Uri is a Built type that store an already built URI in it.
new Uri.Builder(); rerurns a Builder.
Uri.parse("your URI goes here") returns a Built.
and with build() you can change it from Builder to Built.
buildUpon() you can change it from Built to Builder.
Here is what you can do
Uri.Builder builder = Uri.parse("URL").buildUpon();
// here you created a builder, made an already built URI with Uri.parse
// and then change it to builder with buildUpon();
Uri built = builder.build();
//when you want to change your URI, change Builder
//when you want to use your URI, use Built
and also the opposite:-
Uri built = new Uri.Builder().build();
// here you created a reference to a built URI
// made a builder with new Uri.Builder() and then change it to a built with
// built();
Uri.Builder builder = built.buildUpon();
hope my answer helped :) <3
for the example in the second Answer I used this technique for the same URL
http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("api.openweathermap.org")
.appendPath("data")
.appendPath("2.5")
.appendPath("forecast")
.appendPath("daily")
.appendQueryParameter("q", params[0])
.appendQueryParameter("mode", "json")
.appendQueryParameter("units", "metric")
.appendQueryParameter("cnt", "7")
.appendQueryParameter("APPID", BuildConfig.OPEN_WEATHER_MAP_API_KEY);
then after finish building it get it as URL like this
URL url = new URL(builder.build().toString());
and open a connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
and if link is simple like location uri, for example
geo:0,0?q=29203
Uri geoLocation = Uri.parse("geo:0,0?").buildUpon()
.appendQueryParameter("q",29203).build();
Using appendEncodePath() could save you multiple lines than appendPath(), the following code snippet builds up this url: http://api.openweathermap.org/data/2.5/forecast/daily?zip=94043
Uri.Builder urlBuilder = new Uri.Builder();
urlBuilder.scheme("http");
urlBuilder.authority("api.openweathermap.org");
urlBuilder.appendEncodedPath("data/2.5/forecast/daily");
urlBuilder.appendQueryParameter("zip", "94043,us");
URL url = new URL(urlBuilder.build().toString());
Best answer: https://stackoverflow.com/a/19168199/413127
Example for
http://api.example.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7
Now with Kotlin
val myUrl = Uri.Builder().apply {
scheme("https")
authority("www.myawesomesite.com")
appendPath("turtles")
appendPath("types")
appendQueryParameter("type", "1")
appendQueryParameter("sort", "relevance")
fragment("section-name")
build()
}.toString()
You can do that with lambda expressions;
private static final String BASE_URL = "http://api.example.org/data/2.5/forecast/daily";
private String getBaseUrl(Map<String, String> params) {
final Uri.Builder builder = Uri.parse(BASE_URL).buildUpon();
params.entrySet().forEach(entry -> builder.appendQueryParameter(entry.getKey(), entry.getValue()));
return builder.build().toString();
}
and you can create params like that;
Map<String, String> params = new HashMap<String, String>();
params.put("zip", "94043,us");
params.put("units", "metric");
Btw. If you will face any issue like “lambda expressions not supported at this language level”, please check this URL;
https://stackoverflow.com/a/22704620/2057154

how to get the default HTTP USER AGENT from the android device?

How to get the default HTTP USER AGENT and its default settings from the android device?
thanks
Nohsib
as Varundroid mentioned in his answer,
String userAgent = System.getProperty("http.agent");
is better way to do it for Android 2.1 and above.
====================
From android source code.
public static String getDefaultUserAgent() {
StringBuilder result = new StringBuilder(64);
result.append("Dalvik/");
result.append(System.getProperty("java.vm.version")); // such as 1.1.0
result.append(" (Linux; U; Android ");
String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
result.append(version.length() > 0 ? version : "1.0");
// add the model for the release build
if ("REL".equals(Build.VERSION.CODENAME)) {
String model = Build.MODEL;
if (model.length() > 0) {
result.append("; ");
result.append(model);
}
}
String id = Build.ID; // "MASTER" or "M4-rc20"
if (id.length() > 0) {
result.append(" Build/");
result.append(id);
}
result.append(")");
return result.toString();
}
Edit: See Prakash's answer, which is better for 2.1+.
Try http://developer.android.com/reference/android/webkit/WebSettings.html#getUserAgentString
Note that this User Agent will only apply for the embedded WebKit browser that's used by default in Android. Unfortunately, you'll need to create a new WebView object to get the user agent. Fortunately, the user agent doesn't change often, so you should only need to run this code once in your application lifetime (unless don't care about performance). Just do:
String userAgent = new WebView(this).getSettings().getUserAgentString();
Alternatively, you can use the JavaScript method navigator.getUserAgent().
When you use web view to access the user-agent, make sure you run the
new WebView(this).getSettings().getUserAgentString();
on the UI thread.
If you want access the user agent on background thread.
use
System.getProperty("http.agent")
To check whether a user-agent is valid or not use this
https://deviceatlas.com/device-data/user-agent-tester
Android get user agent
An alternative
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
String userAgent = WebSettings.getDefaultUserAgent(context);
}

Categories

Resources