Authorization is required to fetch information from the Google Play Developer API.
I know how to do this with Postman, but implementing authorization is much more cumbersome (redirect url, handling redirects, and so on...)
These would be the steps when you already have setup the auth data inside the Google Developer API Console.
1.) GET https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://www.myurl.com/oauth2callback&client_id=1234567890.apps.googleusercontent.com
2.) get code which was sent to redirect url.
3.) POST https://accounts.google.com/o/oauth2/token
with
grant_type:authorization_code
code:[the code I got before]
client_id:1234567890.apps.googleusercontent.com
client_secret:[my client secret]
4.) Invoke GET https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/token
with:
Scope: https://www.googleapis.com/auth/androidpublisher
and:
access_token as query parameter I got before.
Now I want to do all this programmatically. Obviously not so easy. I thought the Google API Client Libraries will help, but I don't see, how these lib can help me with my use case.
For example classes like GoogleAuthorizationCodeFlow expect a user id at the moment of the request, but I not necessarily have one at this moment, so I wonder how this API should be used in a clean way.
Is there a clean way to handle OAuth2.0 easier / programmatically with some API to access Google Play Developer API? Otherwise I must implement it manually.
After lots of headache (like always with Google APIs and services) I figured out how one can access Google Play Developer API information (like billing) by using existing APIs.
1.) Create in Developer API Console a service account (JSON) key:
2.) Download this service-account-private-key.json file (don't mistake it with the OAuth2.0 client secret file!).
3.) In Google Play Developer Console go to Settings -> Users & Permissions -> Invite New User and set as user e-mail of the new user the client_email from the downloaded file. Assign the access rights you want to give to this users via the checkboxes inside this view (for example 'View financial data').
4.) Add the proper dependency to your project (version ...-1.23.0 does not work for me):
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-androidpublisher</artifactId>
<version>v2-rev50-1.22.0</version>
</dependency>
5.) Load the service-account-private-key.json file into your application. In my case it's a webserver:
#Singleton
#Startup
public class WebserverConfiguration
{
private String serviceAccountPrivateKeyFilePath;
/** Global instance of the HTTP transport. */
public static HttpTransport HTTP_TRANSPORT;
/** Global instance of the JSON factory. */
public static JsonFactory JSON_FACTORY;
private GoogleCredential credential;
#PostConstruct
public void init()
{
assignServiceAccountFileProperty();
initGoogleCredentials();
}
public String getServiceAccountPrivateKeyFilePath()
{
return serviceAccountPrivateKeyFilePath;
}
public GoogleCredential getCredential()
{
return credential;
}
private void initGoogleCredentials()
{
try
{
newTrustedTransport();
newJsonFactory();
String serviceAccountContent = new String(Files.readAllBytes(Paths.get(getServiceAccountPrivateKeyFilePath())));
InputStream inputStream = new ByteArrayInputStream(serviceAccountContent.getBytes());
credential = GoogleCredential.fromStream(inputStream).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
}
catch (IOException | GeneralSecurityException e)
{
throw new InitializationException(e);
}
}
private void newJsonFactory()
{
JSON_FACTORY = JacksonFactory.getDefaultInstance();
}
private void assignServiceAccountFileProperty()
{
serviceAccountPrivateKeyFilePath = System.getProperty("service.account.file.path");
if (serviceAccountPrivateKeyFilePath == null)
{
throw new IllegalArgumentException("service.account.file.path UNKNOWN - configure it as VM startup parameter in Wildfly");
}
}
private static void newTrustedTransport() throws GeneralSecurityException, IOException
{
if (HTTP_TRANSPORT == null)
{
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
}
}
}
6.) Now I am able the fetch Google Play Developer API information, e.g. reviews:
private void invokeGoogleApi() throws IOException
{
AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
AndroidPublisher.Reviews reviews = publisher.reviews();
ReviewsListResponse reviewsListResponse = reviews.list("the.packagename.of.my.app").execute();
logger.info("review list response = " + reviewsListResponse.toPrettyString());
}
This worked.
I cannot test it yet, but I'm sure that fetching the billing information works as well:
private SubscriptionPurchase getPurchase() throws IOException
{
AndroidPublisher publisher = new AndroidPublisher.Builder(WebserverConfiguration.HTTP_TRANSPORT, WebserverConfiguration.JSON_FACTORY, configuration.getCredential()).setApplicationName("The name of my app on Google Play").build();
AndroidPublisher.Purchases purchases = publisher.purchases();
SubscriptionPurchase purchase = purchases.subscriptions().get("the.packagename.of.my.app", "subscriptionId", "billing token sent by the app").execute();
//do something or return
return purchase;
}
There are complete code samples and documentation for doing this in Java here
In the Java source code this authorizes like this
private static Credential authorizeWithServiceAccount(String serviceAccountEmail)
throws GeneralSecurityException, IOException {
log.info(String.format("Authorizing using Service Account: %s", serviceAccountEmail));
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(serviceAccountEmail)
.setServiceAccountScopes(
Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER))
.setServiceAccountPrivateKeyFromP12File(new File(SRC_RESOURCES_KEY_P12))
.build();
return credential;
}
Related
I am trying to setup youtube live streaming APIs using service account delegation. I have done all the necessary steps for service account delegation on my domain.
I have a youtube channel owned by a user with email id of this domain name. Channel has more than 10k subscribers and has all the necessary permissions to live stream (I can live stream via youtube studio).
While using youtube java APIs, i am getting this error :
{
"code" : 403,
"errors" : [ {
"domain" : "youtube.liveBroadcast",
"message" : "The user is blocked from live streaming.",
"reason" : "livePermissionBlocked",
"extendedHelp" : "https://support.google.com/youtube/answer/2853834"
} ],
"message" : "The user is blocked from live streaming."
}
I am attaching my code for reference
private static final Collection<String> SCOPES =
Arrays.asList("https://www.googleapis.com/auth/youtube.force-ssl");
private static final String APPLICATION_NAME = "youtubeLive";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/**
* Create an authorized Credential object.
*
* #return an authorized Credential object.
* #throws IOException
*/
public static Credential authorize(final NetHttpTransport httpTransport) throws IOException, GeneralSecurityException {
// Load client secrets.
InputStream in = new FileInputStream(CLIENT_SECRETS);
// GoogleClientSecrets clientSecrets =
// GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// // Build flow and trigger user authorization request.
// GoogleAuthorizationCodeFlow flow =
// new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES)
// .build();
// Credential credential = new AuthorizationCodeInstalledApp(flow, null).authorize("user");
// GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(CLIENT_SECRETS))
// .createScoped(SCOPES);
GoogleCredential credential = new GoogleCredential.Builder()
.setServiceAccountScopes(SCOPES)
.setServiceAccountPrivateKeyFromP12File(new File("/Users/ashishjindal/Downloads/youtubelive-291213-be89f6b31144.p12"))
.setServiceAccountId("a******#youtubelive****.iam.gserviceaccount.com")
.setServiceAccountUser("USER#MY_DOMAIN.COM")
.setJsonFactory(JSON_FACTORY)
.setTransport(httpTransport)
.build();
return credential;
}
/**
* Build and return an authorized API client service.
*
* #return an authorized API client service
* #throws GeneralSecurityException, IOException
*/
public static YouTube getService() throws GeneralSecurityException, IOException {
final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
Credential credential = authorize(httpTransport);
return new YouTube.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
#Scheduled(fixedDelay = 1000l)
public void test() throws IOException, GeneralSecurityException {
YouTube youtubeService = getService();
LiveBroadcast liveBroadcast = new LiveBroadcast();
// Add the contentDetails object property to the LiveBroadcast object.
LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
contentDetails.setEnableClosedCaptions(true);
contentDetails.setEnableContentEncryption(true);
contentDetails.setEnableDvr(true);
contentDetails.setEnableEmbed(true);
contentDetails.setEnableAutoStart(true);
contentDetails.setRecordFromStart(true);
contentDetails.setStartWithSlate(true);
liveBroadcast.setContentDetails(contentDetails);
LiveBroadcastSnippet snippet = new LiveBroadcastSnippet();
snippet.setScheduledEndTime(new DateTime("2030-10-10T00:00:00"));
snippet.setScheduledStartTime(new DateTime("2029-10-10T00:00:00"));
snippet.setTitle("Test broadcast");
snippet.setChannelId("CHANNEL ID OWNED BY MY USER");
liveBroadcast.setSnippet(snippet);
LiveBroadcastStatus status = new LiveBroadcastStatus();
status.setPrivacyStatus("unlisted");
liveBroadcast.setStatus(status);
YouTube.LiveBroadcasts.Insert request = youtubeService.liveBroadcasts()
.insert("snippet,contentDetails,status", liveBroadcast);
liveBroadcast = request.execute();
System.out.println(response);
}
EDIT : I have identified the root cause. I was passing the channel Id which belonged to a brand account which is further owned by this user. A user can have multiple brand accounts on youtube. Now my new issue is how to impersonate brand account using service-account.
Some useful threads I found :
YouTube API and brand account
Using Youtube Data API to Edit with Brand Account Playlist
The YouTube APIs does not support service accounts (as other Google APIs do).
Here is quote from the official API doc Move from ClientLogin to OAuth 2.0, the section Service Accounts do not work with the YouTube API (the emphasis below is mine):
Service accounts do not work for YouTube Data API calls because service accounts require an associated YouTube channel, and you cannot associate new or existing channels with service accounts. If you use a service account to call the YouTube Data API, the API server returns an error with the error type set to unauthorized and the reason set to youtubeSignupRequired.
Moreover, here is a text extracted from another place of the official docs that states that fact once more (the emphasis below is also mine):
This error is commonly seen if you try to use the OAuth 2.0 Service Account flow. YouTube does not support Service Accounts, and if you attempt to authenticate using a Service Account, you will get this error.
The context from which I extracted the above official statement is not subsumed to that you've shown above. Nonetheless, the fact remains.
Yet another quote asserting the above mentioned fact, this time from the Live Streaming API docs themselves (the emphasis below is mine too):
The service account flow supports server-to-server interactions that do not access user information. However, the YouTube Live Streaming API does not support this flow. Since there is no way to link a Service Account to a YouTube account, attempts to authorize requests with this flow will generate a NoLinkedYouTubeAccount error.
Consequently, you have to acknowledge that you cannot initiate a live broadcast using YouTube's corresponding APIs by means of a service account.
I am developing an app whose frontend is written using React.js and the backend REST API is written using the Spring framework. I wanted to add social logins to my website, so after days of googling and research, I understood that OAuth2 is the solution. I came to know that the frontend should handle getting the authorization token from the Resource Server(Facebook here) and my backend(java) should validate that token and connect with Facebook to get an access token. Then that access token should be stored in my database along with the user details(e.g email).
Here is my requirement, once the user clicks on the "Continue with Facebook" button, my app should create there account in my own database using details - email and Name(the signup feature). And later whenever they click on this button again, they will be logged in not sign up. The way other websites handle it.
As of now, I have the button working in my app, which brings me the authorization token from Facebook.
Can someone please guide me the path I should follow here.
Also, any special attention to some error handling I should follow.
Here's the general approach using Spring Boot as a REST API backed by Spring Data JPA and Spring Security that works for iOS and ember.js together. There's probably libraries and what not that you can use but I'm just going to outline the fundamental flow.
Your user object needs a one to one mapping to a facebook account. Best practice would involve encrypting the authToken before storing in the DB
#Entity
class FacebookAccount {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
Long id
String facebookUserId
String authToken
#OneToOne
#JoinColumn(name="user_id")
User user
}
#Entity
class User{
...
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
FacebookAccount facebookAccount
}
Use the facebook Javascript SDK to get a User Access Token and the User's Facebook User ID. You'll get a response back from facebook in your react app that looks like this in the successful case:
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
reauthorize_required_in:'...'
signedRequest:'...',
userID:'...'
}
}
Hit some login endpoint with the info received in step 2 like /login/facebook. I cannot predict how your app is structured. In my app, this code is handled by my Authentication Filter that implements GenericFilterBean. I pass a header X-Auth-Facebook with the token.
Verify the token. I'm doing this in a class that implements AuthenticationProvider within the Authentication authenticate(Authentication authentication) throws AuthenticationException method. This class will need your App's Access Token accessToken and the user's Token userAccessToken:
URIBuilder builder = URIBuilder.fromUri(String.format("%s/debug_token", "https://graph.facebook.com"))
builder.queryParam("access_token", accessToken)
builder.queryParam("input_token", userAccessToken)
URI uri = builder.build()
RestTemplate restTemplate = new RestTemplate()
JsonNode resp = null
try {
resp = restTemplate.getForObject(uri, JsonNode.class)
} catch (HttpClientErrorException e) {
throw new AuthenticationServiceException("Error requesting facebook debug_token", e)
}
Boolean isValid = resp.path("data").findValue("is_valid").asBoolean()
if (!isValid)
throw new BadCredentialsException("Token not valid")
String fbookUserId = resp.path("data").findValue("user_id").textValue()
if (!fbookUserId)
throw new AuthenticationServiceException("Unable to read user_id from facebook debug_token response")
// spring data repository that finds the FacebookAccount by facebook user id
FacebookAccount fbookAcct = facebookAccountRepository.findByFacebookUserId(fbookUserId)
if(!fbookAcct){
// create your user here
// save the facebook account as well
} else{
// update the existing users token
fbookAcct.authToken = userAccessToken
facebookAccountRepository.save(fbookAcct)
}
// finish the necessary steps in creating a valid Authentication
I, personally, then create a token that my client's use when accessing my API (rather than have them continue to pass the facebook token with all requests).
I also need more user provided information to create the user (a chosen username, agreeing to terms and conditions, etc). So my actual implementation throws an EntityNotFoundException instead of creating the user, which my clients then use to pop up a registration form that provides only the fields I cannot get from facebook. On submit of this from the client, I hit my /signup/facebook endpoint with the facebook token and what's needed to create my user. I fetch the profile from facebook and create the user (automatically logging them in the process).
Edit: If you want to use Spring 0Auth, you could follow the example for creating a Spring 2 Oauth Rest Template
#Bean
public OAuth2ProtectedResourceDetails facebook() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("facebook");
details.setClientId("233668646673605");
details.setClientSecret("33b17e044ee6a4fa383f46ec6e28ea1d");
details.setAccessTokenUri("https://graph.facebook.com/oauth/access_token");
details.setUserAuthorizationUri("https://www.facebook.com/dialog/oauth");
details.setTokenName("oauth_token");
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
#Bean
public OAuth2RestTemplate facebookRestTemplate(OAuth2ClientContext clientContext) {
OAuth2RestTemplate template = new OAuth2RestTemplate(facebook(), clientContext);
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON,
MediaType.valueOf("text/javascript")));
template.setMessageConverters(Arrays.<HttpMessageConverter<?>> asList(converter));
return template;
}
and then in use:
public String photos(Model model) throws Exception {
ObjectNode result = facebookRestTemplate
.getForObject("https://graph.facebook.com/me/friends", ObjectNode.class);
ArrayNode data = (ArrayNode) result.get("data");
ArrayList<String> friends = new ArrayList<String>();
for (JsonNode dataNode : data) {
friends.add(dataNode.get("name").asText());
}
model.addAttribute("friends", friends);
return "facebook";
}
I took the above request for friends from the project. it shouldn't be hard to tailor the above code I showed with debug_token to use the Spring OAuth rest template. Hope this helps :)
My project is a java spark project that I have hosted on heroku. A part of the project requires that I download a particular file from my google drive into the application. I managed to set up everything when my application was running locally but as soon as I deployed the app it stopped working. This was regardless of the fact that when the app was running locally I used an Oauth2 client ID of type other and when I deployed the application I created a new one of type web application.
Below is a snippet of the authentication and download code:
public class AutoCalls {
/** Application name. */
private static final String APPLICATION_NAME = "calls-made";
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("target/classes/auth"), ".credentials/calls-made");
private static FileDataStoreFactory DATA_STORE_FACTORY;
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static HttpTransport HTTP_TRANSPORT;
private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (GeneralSecurityException | IOException t) {
System.exit(1);
}
}
public static void startDownload() throws IOException, ParseException {
Drive serv = getDriveService();
// drive stuff deleted
}
public static Credential authorize() throws IOException {
InputStream in = new FileInputStream("target/classes/auth/client_secret_*****************************************.apps.googleusercontent.com.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
}
public static Drive getDriveService() throws IOException {
Credential credential = authorize();
return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
}
Currently when I try to initiate the download I get a URL in the Heroku logs a follows:
2017-02-20T10:32:28.656820+00:00 app[web.1]: Please open the following address in your browser:
2017-02-20T10:32:28.656908+00:00 app[web.1]: https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=************-vvdi7u6bmp1vc90sdidtnuiftdi1t49c.apps.googleusercontent.com&redirect_uri=http://localhost:48085/Callback&response_type=code&scope=https://www.googleapis.com/auth/drive
When I try open the URL in a browser I get an error:
Error: redirect_uri_mismatch
I cannot find any good step by step tutorial on accessing google drive contents on a java web application so any help would be arreiciated.
Generally, if OAuth works on server-A but not on server-B, it's because the redirect URL hasn't been configured correctly on the API Console. There is no reason why you would need to use a different client-ID because a single client-ID can be configured with multiple URLs, eg your local host and your heroku server. Another possibility is the use of https.
There is a separate problem in your code where you iterate on lista.isEmpty(). You should be iterating on nextPageToken != null. See the answer to Google drive rest API, Download files from root folder only
Implemented Spring OAuth2 security and getting same access token when logging with the same user but from different device. When i logout from any one of these devices(revoke Token)other devices are also getting logged out. Is it a expected behavior or i am missing something ? hoping that sharing the massive code will not help much so kept the question short and simple.
The default behaviour of the DefaultTokenServices is to re-use existing tokens (based on the behaviour of the existing TokenStore implementations)
http://forum.spring.io/forum/spring-projects/security/oauth/121797-multiple-valid-oauth-access-tokens-for-same-client
If you want every device to be given different access_token then create your own AuthenticationKeyGenerator e.g. send your device id on authorization process and let your AuthenticationKeyGenerator process that device id to create access_token specific for that device.
(Please read org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator code to put the following solution into context)
DefaultAuthenticationKeyGenerator is available in spring. I just created a custom version with the same code with one extension, i.e., device_id sent from the client as a request parameter is retrieved from OAuth2Authentication as follows;
String deviceId = authentication.getOAuth2Request().getRequestParameters().get("device_id")
and then is put into the values map (used to generate the token finally). Hence the device_id becomes a part of the token resulting in a unique token per device.
Following is the full solution which is mostly the DefaultAuthenticationKeyGenerator apart from the bit explained above.
public class CustomAuthenticationKeyGenerator implements AuthenticationKeyGenerator
{
private static final String CLIENT_ID = "client_id";
private static final String SCOPE = "scope";
private static final String USERNAME = "username";
#Override
public String extractKey(OAuth2Authentication authentication) {
Map<String, String> values = new LinkedHashMap<String, String>();
OAuth2Request authorizationRequest = authentication.getOAuth2Request();
if (!authentication.isClientOnly()) {
values.put(USERNAME, authentication.getName());
}
values.put(CLIENT_ID, authorizationRequest.getClientId());
if (authorizationRequest.getScope() != null) {
values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope()));
}
String deviceId = authorizationRequest.getRequestParameters().get(CustomHeader.device_id.name());
if(deviceId != null && !deviceId.isEmpty()) {
values.put("device_id", deviceId);
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK).");
}
try {
byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
return String.format("%032x", new BigInteger(1, bytes));
}
catch (UnsupportedEncodingException e) {
throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK).");
}
}
}
For those who are facing the same issue can work on the replied solution by MangEngkus, for precise solution you can also refer this link Spring OAuth2 Generate Access Token per request to the Token Endpoint
Is it possible enable the Google Placess API WebService to allow cross-origin requests from my domain so that I can access the service directly from the browser? I'v been experimenting with the API-keys by creating a Browser API key and then adding my domain to the referers list, but to no avail. Not sure if that is what the refeferer property is for anyway.
Is this limitation by design, or am I missing something here?
Google Places API WebService is the service that I want to use. Neither the Places Autocomplete or Places Search in the Places Library are suitable for my particular requirement.
Cheers
Stian
This is a client-side based limitation, so the short answer is: no.
However there are websites and services that try to surmount this problem by using scripts (loading them on the fly).
Have a look here and here (these articles are about generic cross-domain AJAX requests)
The Places-API is also available inside the Maps-Javascript-API, you don't need to struggle with cross-origins there.
Let me say its impossible to get around .I tried using java instead the code just works for http request(i used here is for graph.facebook.com):
public class search {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
System.getProperties().put("http.proxyHost", "172.16.0.2");
System.getProperties().put("http.proxyPort", "8080");
JSONObject json = readJsonFromUrl("http://maps.googleapis.com/maps/api/place/nearbysearch/json?key=AIzaSyBRlMLIdoTk-j4OZCucR47rVMLhMmvZVRw&type=hospital&location=12.8213125%2C80.0442&radius=500&_=1427359809583");
System.out.println(json.toString());
// System.out.println(json.get("about"));
// System.out.println("hello ");
}
}
If you replace the link with places api web search it will not work,the reason is that google does not give its services on HTTP domain,,, and my code only works on HTTP domain(not HTTPS)