I'm creating an Android app and trying to use Google Places API through Google APIs Client. I've been following this example:
http://ddewaele.blogspot.com/2011/05/introducing-google-places-api.html
I'm having problems creating a HTTP Transport Object to use in creating the HTTP Request Factory. Everything compiles fine in eclipse, but when I debug while running on my phone, I get a classnotfound on the first line here:
HttpTransport transport = new ApacheHttpTransport();
HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
public static HttpRequestFactory createRequestFactory(HttpTransport transport) {
return transport.createRequestFactory(new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
request.headers.authorization = "...";
}
});
}
According to the JavaDoc for the HTTP Transport Class:
Android:
Starting with SDK 2.3, strongly recommended to use
com.google.api.client.javanet.NetHttpTransport. Their Apache HTTP Client
implementation is not as well maintained.
For SDK 2.2 and earlier, use com.google.api.client.apache.ApacheHttpTransport.
com.google.api.client.javanet.NetHttpTransport
is not recommended due to some bugs in
the Android SDK implementation of
HttpURLConnection.
I'm running on 2.2, so I tried using the ApacheHTTPTransport. I've also tried the NetHTTPTransport, but I get the same thing (classnotfound).
Any ideas/examples?
Thanks!
In order to run the Places API in an Android environment using the Google APIs Client, you'll need to have the following dependencies in your Android project :
M2_REPO/commons-codec/commons-codec/1.3/commons-codec-1.3.jar
M2_REPO/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar
M2_REPO/com/google/api/client/google-api-client/1.4.1-beta/google-api-client-1.4.1-beta.jar
M2_REPO/com/google/api/client/google-api-client-googleapis/1.4.1-beta/google-api-client-googleapis-1.4.1-beta.jar
M2_REPO/com/google/code/gson/gson/1.6/gson-1.6.jar
M2_REPO/com/google/guava/guava/r08/guava-r08.jar
M2_REPO/org/apache/httpcomponents/httpclient/4.0.3/httpclient-4.0.3.jar
M2_REPO/org/apache/httpcomponents/httpcore/4.0.1/httpcore-4.0.1.jar
M2_REPO/org/codehaus/jackson/jackson-core-asl/1.6.5/jackson-core-asl-1.6.5.jar
M2_REPO/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar
Related
I am trying to send a POST transaction from Xamarin.Forms using TLS1.2 but I see them arriving to the server as TLS 1.1.
I have configured Android options:
HttpClient impletemtation as Android
SSL/TLS implementation as Native TLS 1.2+
I am implementing and executing in VisualStudio 2017, and using Android 6.0 in the emulator.
Regarding the code, I set some enviroment variables:
System.Environment.SetEnvironmentVariable("MONO_TLS_PROVIDER", "btls");
System.Environment.SetEnvironmentVariable("XA_TLS_PROVIDER", "btls");
System.Environment.SetEnvironmentVariable("XA_HTTP_CLIENT_HANDLER_TYPE", "Xamarin.Android.Net.AndroidClientHandler");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally, POST is sent with:
using (HttpClient client = new HttpClient())
or
using (HttpClient client = new HttpClient(new NativeMessageHandler()))
or
using (HttpClient client = new HttpClient(new Xamarin.Android.Net.AndroidClientHandler()))
{
try
{
HttpResponseMessage responseHttp = await client.PostAsync(new Uri(new Uri(Constants.ApiBaseUrl), "authorize"), content);
...
Where Constants.ApiBaseUrl contains a url with https://<> format.
The problem is, when POST is sent I have no exceptions, but in my server I see with Wireshark the transaction as:
I have also tried in other way, using:
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(new Uri(new Uri(Constants.ApiBaseUrl), "authorize"));
httpWebRequest.Method = "POST";
httpWebRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream sw = httpWebRequest.GetRequestStream();
sw.Write(contentByte, 0, contentByte.Length);
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
With and without my own certificates using:
httpWebRequest.ClientCertificates = cryptoSvc.x509HostCertificates;
In this case, if I use
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I get the exception
RestService-SendJsonDataAsync ERROR: Error: SecureChannelFailure
(**Ssl error:100000f0:SSL routines:OPENSSL_internal:UNSUPPORTED_PROTOCOL**
at /Users/builder/jenkins/workspace/xamarin-android/xamarin-android/external/mono/external/boringssl/ssl/handshake_client.c:808)
Without that line it is also arriving as TLS1.1.
Does anyone have any idea or suggestion about what is wrong in my case, please?
Thanks so much for your time and help.
I believe in Android 6.0, TLS 1.2 is enabled by default:
https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
But, you have BTLS configuration and Native TLS 1.2, I think these are conflicting. BTLS is the Boring TLS implementation, designed to provide TLS 1.2 support on older versions of Android. I think you can safely remove those lines.
I'd first confirm what the server is allowing in terms of security and if possible have the server limit HTTPS connections to only TLS 1.2.
If you'd like to try forcing only TLS 1.2 connections on the client side, take a look at this answer (note this is in Java, but the process is the same):
How to set TLS version on apache HttpClient
I was able to work around this problem by downloading and installed VS 2022 Community - Preview. I then created a MAUI .net app and used the same code that I used in VS 2019.
I have some code that I am trying to get to work with Android API 21. It was written with a version of HTTP Client 3.x and Android uses a version of HTTP Client that is definitely 4.x but not 4.5. So I am wondering how to update this section of code specifically
if(getProxy() != null) {
client.getHostConfiguration().setProxy(getProxy().getHost(),getProxy().getPort());
if (HttpProxyCredentials.isProxySet()) {
AuthScope authScope = new AuthScope(getProxy().getHost(), getProxy().getPort());
client.getState().setProxyCredentials(authScope, new NTCredentials(HttpProxyCredentials.getUserName(),
HttpProxyCredentials.getPassword(),
"",HttpProxyCredentials.getDomain()));
Any one know how to do this Android?
I am developing an android app for an online Newspaper company. The company already developed and hosted their APIs on the Google App Engine with OAuth 2.0 support.
So I am to develop an android app that communicates with their deployed backend API with OAuth 2.0 support and fetch the contents Response from their assigned Google API Explorer.
so according to the Google cloud endpoints documentation for android clients(like my app) trying to make authenticated calls to the endpoints with OAuth 2.0 support, I was directed to:
Configure my Android Client(my android app) to provide credentials to the service object
se the account picker to support user choice of login accounts.
I followed the instructions on the Google Cloud Endpoint website but I didn't understand the sample codes that was used to explain, so I tried coming up with this:
class EndpointsAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new AndroidJsonFactory();
try {
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(CLIENT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"))
.setServiceAccountPrivateKeyFromP12File(new File("file.p12"))
.build();
/*so now what do I do with the credential object
and how do I set the root URL (https://project-id-endpoints.appspot.com/_ah/api)
that the android client(this android app)
will connect to in the backend API call
*/
}
catch(GeneralSecurityException gse){
gse.printStackTrace();
}
catch(IOException ioe){
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
whenever I run my codes, the log report on the Google Developer Console is saying
"Uauthorised access" meaning the authentication call is not working...
Below is my code for opening a GET URL connection to one of the API service content:
public String open() throws IOException{
InputStream inputStream = null;
int len = 500;
try {
URL url = new URL("https://project-name-api-endpoints.appspot.com/_ah/api/core/v5.1.1/info/category/en");
URLConnection urlConnection = url.openConnection();
inputStream = urlConnection.getInputStream();
String content = readIt(inputStream, len);
return content;
}//end try
finally {
if(inputStream != null)
{
inputStream.close();
}
}
}
The question I have is:
What do I do with the credential object and how do I set the root URL (https://project-id-endpoints.appspot.com/_ah/api) that the android client(this android app) will connect to in the backend API call
The problem is that you are not using those credentials you set up when calling the endpoint. That connection you are making is completely unaware of all the OAuth settings and wonderful stuff you get from endpoints + Android.
Ideally what you need to do is:
1) Create the client libraries for Android from your endpoints (As explained here). Do not make "manual" (through URLConenction) calls to your endpoints, although it's technically possible it's absolutely not recommended.
2) With those libs (jars) included in your project all you need to do is call whatever method you need (as explained here) and the libraries will include all required authorization headers, etc based on your app settings. You don't need to worry about anything else regarding OAuth.
TIP: Make sure to include all of your developer's SHA debug signatures on the authorization on Google console. If you don't, you'll only be able to call the endpoints from your "prodcution" app.
Netcipher is an Android Library Project that provides multiple means to improve network security in mobile applications. The “Onion” name refers to not only the Onion Routing concept used by Tor (which provides anonymity and resistance to traffic surveillance), but also the idea of multiple layers of security that any application should utilize.
More specifically this library provides:
1. Stronger Sockets: Through support for the right cipher suites, pinning and more, we ensure your encrypted connections are as strong as possible.
2. Proxied Connection Support: HTTP and SOCKS proxy connection support for HTTP and HTTP/S traffic through specific configuration of the Apache HTTPClient library
https://guardianproject.info/code/netcipher/
You need to implement your own Client that will execute Retrofit request on Netcipher http client.
Translate Request to appropriate Netcipher request (copy http method, headers, body)
Execute the translated request on Netcipher http client
Obtain response and translated it to retrofit Response (copy http status code, response, headers)
Return response to be deserialized to type.
Pass your Client to RestAdapter.Builder.
Done.
public class NetcipherClient implements Client{
private Context mContext;
public NetcipherClient(Context context){
mContext = context;
//As far as I could see from the sample, Netcipher seems to be dependant on application `Context`.
}
#Override
public retrofit.client.Response execute(retrofit.client.Request request) throws IOException {
//Set up configuration for Netcipher (proxy, timeout etc)
// Translate Request to Netcipher request
// Execute and obtain the response
// Build Response from response
return response;
}
}
We've recently implemented support for OkHTTP in NetCipher so it should be easy to add Tor support to Retrofit via OkHTTP. Here's how:
compile 'info.guardianproject.netcipher:netcipher-okhttp3:2.0.0-alpha1'
The core of this is just running the method to set things up:
StrongOkHttpClientBuilder
.forMaxSecurity(this)
.withTorValidation()
.build(this);
See the included sample-okhttp3 project for a full example, which is part of the git repo https://github.com/guardianproject/NetCipher
Except Tor-like routing OkHttp also have the certificate pinning ability & proxy support. And it works with Retrofit out-of-the-box! So, if Tor-like functions are not so important for you, I recommend to utilize OkHttp's awesomeness. Otherwise, answer by #NikolaDespotoski is your perfect choice.
I'm trying to test out an updated appengine version without ruining my live version. The current code is:
themeendpoint.Builder endpointBuilder = new themeendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(),
new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest httpRequest) throws IOException {
}
}
);
themeendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
Which works fine for the default version. I'm trying to access the "dev" version that I uploaded. I understand that normally you are supposed to add the version at the beginning like "dev.project.appspot" but I'm struggling to get this into the Android App. I tried adding the following:
endpointBuilder.setRootUrl("https://dev.project.appspot.com/_ah/api/");
Just before creating the endpoint. When running the app I get the following error:
java.io.IOException: Hostname 'dev.project.appspot.com' was not verified
I'm at a loss as to how to access my non-default version.
Turns out I almost had it right. Per this link I need to use "-dot-" notation for HTTPS. Plus, I was missing a small piece of the URL. Full line of code is:
endpointBuilder.setRootUrl("https://dev-dot-project.appspot.com/_ah/api/");