I get a error message below .. when I run the code for hitting google Calendar API.There is a client_secrets.json file that has the credentials (client ID and redirectID) . I unzipped and ran the package google gave, it successfully runs and I could see that by a "Success,Add code here"message. after which it throws me a nullpointer exception for which I'm not sure what has gone wrong.please help. Downloaded the sample project from here https://developers.google.com/api-client-library/java/apis/calendar/v3
May 01, 2014 12:59:42 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for everybody: C:\Users\Aishwarya Anand\.store\calendar_sample
May 01, 2014 12:59:42 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for owner: C:\Users\Aishwarya Anand\.store\calendar_sample
Success! Now add code here.
inserting event ...
Aish Event from the new Google API
2014-05-01T16:59:42.545Z
2014-05-01T17:59:42.545Z
java.lang.NullPointerException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)
at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:96)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:85)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81)
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:88)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.auth.oauth2.Credential.executeRefreshToken(Credential.java:570)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.google.api.services.samples.calendar.cmdline.CalendarSample.insertEventTest(CalendarSample.java:170)
at com.google.api.services.samples.calendar.cmdline.CalendarSample.main(CalendarSample.java:116)
Class here,
package com.google.api.services.samples.calendar.cmdline;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.*;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Date;
import java.util.TimeZone;
public class CalendarSample {
/**
* Be sure to specify the name of your application. If the application name is {#code null} or
* blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
*/
private static final String APPLICATION_NAME = "Caritas-CalendarAPI/1.0";
/** Directory to store user credentials. */
private static final java.io.File DATA_STORE_DIR =
new java.io.File(System.getProperty("user.home"), ".store/calendar_sample");
/**
* Global instance of the {#link DataStoreFactory}. The best practice is to make it a single
* globally shared instance across your application.
*/
private static FileDataStoreFactory dataStoreFactory;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport httpTransport;
#SuppressWarnings("unused")
private static Calendar client;
/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
// load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(CalendarSample.class.getResourceAsStream("/client_secrets.json")));
// Set up authorization code flow.
// Ask for only the permissions you need. Asking for more permissions will
// reduce the number of users who finish the process for giving you access
// to their accounts. It will also increase the amount of effort you will
// have to spend explaining to users what you are doing with their data.
// Here we are listing all of the available scopes. You should remove scopes
// that you are not actually using.
Set<String> scopes = new HashSet<String>();
scopes.add(CalendarScopes.CALENDAR);
scopes.add(CalendarScopes.CALENDAR_READONLY);
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets, scopes)
.setDataStoreFactory(dataStoreFactory)
.build();
// authorize
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
public static void main(String[] args) {
try {
// initialize the transport
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
// initialize the data store factory
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
// authorization
Credential credential = authorize();
// set up global Calendar instance
client = new Calendar.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
System.out.println("Success! Now add code here.");
insertEventTest();
//getEventList();
//getEventTest();
//sertEventTest();
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(1);
}
private static void getEventList() throws IOException {
String pageToken = null;
do {
Events events = client.events().list("primary").setPageToken(pageToken).execute();
List<Event> items = events.getItems();
for (Event event : items) {
System.out.println(" id: " + event.getId() + "; summary: " + event.getSummary());
}
pageToken = events.getNextPageToken();
} while (pageToken != null);
}
private static void getEventTest() throws IOException {
String eventId = "idkoi3c55lvegs2ev333u28grk5c";
Event event = client.events().get("primary", eventId).execute();
System.out.println(event.getSummary());
}
private static void insertEventTest() throws IOException {
System.out.println("inserting event ...");
Event event = new Event();
event.setSummary("Aish Event from the new Google API");
event.setLocation("Somewhere");
System.out.println(event.getSummary());
Date startDate = new Date();
Date endDate = new Date(startDate.getTime() + 3600000);
DateTime start = new DateTime(startDate, TimeZone.getTimeZone("UTC"));
event.setStart(new EventDateTime().setDateTime(start));
System.out.println(start.toStringRfc3339());
DateTime end = new DateTime(endDate, TimeZone.getTimeZone("UTC"));
event.setEnd(new EventDateTime().setDateTime(end));
System.out.println(end.toStringRfc3339());
Event createdEvent = client.events().insert("primary", event).execute();
System.out.println("event id" + createdEvent.getId());
}
}
Related
I am using the jobs.query API to update the bigquery table records using java.
While running this as a part of stability tests for a longer time, we get an exception. Excpetion occurs almost after 5 hours, 11 hours...
The problem is, exception returns blank error message, blank cause, and blank stack trace. So, in this case, I am not able to find the actual cause of the error.
Request your response on this.
Thanks in advance!
package app;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryScopes;
import com.google.api.services.bigquery.model.QueryRequest;
import com.google.api.services.bigquery.model.QueryResponse;
public class WhereCLause {
//Create Entry Point: Main function
public static void main(String[] args) throws IOException, ParseException {
String projectId = "projectId";
// Create a new Bigquery client authorized via Application Credentials.
Bigquery bigquery = createAuthorizedClient();
String query = "UPDATE datasetId.tableName SET Name = 'RefUpdate' WHERE ID = 001";
System.out.println(query);
executeQuery(query, bigquery, projectId);
}
public static Bigquery createAuthorizedClient() throws IOException {
String jsonFilePath="file.json";
// Create the credential
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
InputStream credentialStream = new FileInputStream(new File(jsonFilePath));
GoogleCredential credential = GoogleCredential.fromStream(credentialStream, transport, jsonFactory);
if (credential.createScopedRequired()) {
credential = credential.createScoped(BigqueryScopes.all());
}
return new Bigquery.Builder(transport, jsonFactory, credential).setApplicationName("BigqueryApplication").build();
}
private static void executeQuery(String querySql, Bigquery bigquery, String projectId) throws IOException {
QueryResponse query = bigquery.jobs().query(projectId, new QueryRequest().setQuery(querySql).setUseLegacySql(true)).execute();
System.out.println(query.getNumDmlAffectedRows());
System.err.println(query.getErrors());
}
}
This is the test code for authentication and insert Account :
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Lists;
import com.google.api.services.mirror.Mirror;
import com.google.api.services.mirror.Mirror.Accounts.Insert;
import com.google.api.services.mirror.model.Account;
import com.google.api.services.mirror.model.AuthToken;
public class InsertAccountWithJava {
private static final String SERVICE_ACCOUNT_EMAIL ="540223414844-tqpuqtbv07klpuuk3q04qha0g88094uu#developer.gserviceaccount.com";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH ="C:/Users/Yuan/Desktop/eyenotes-db176c40f51f.p12";
private static final String ACCOUNT_TYPE = "com.eyenotes";
private static final Collection<String> MIRROR_ACCOUNT_SCOPES =Arrays.asList("https://www.googleapis.com/auth/glass.thirdpartyauth");
private static String userToken = "6164da1732ea09b4";
private static String accountName="zhongmei";
private static String authTokenType ="eyenotes";
private static String authToken="myauthtoken";
public static void main(String[] args) {
try {
Mirror mirror = getMirrorService();
createAccount(mirror, userToken, accountName, authTokenType, authToken);
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
public static Mirror getMirrorService() throws GeneralSecurityException, IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(MIRROR_ACCOUNT_SCOPES)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Mirror service = new Mirror.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
public static void createAccount(Mirror mirror, String userToken, String accountName,
String authTokenType, String authToken) {
try {
Account account = new Account();
List<AuthToken> authTokens = Lists.newArrayList();
AuthToken authToken1 = new AuthToken().setType(authTokenType).setAuthToken(authToken);
authTokens.add(authToken1);
account.setAuthTokens(authTokens);
account.setPassword("zmyl123456");
Insert insert = mirror.accounts().insert(userToken, ACCOUNT_TYPE, accountName, account);
insert.execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
============================================================================
I got the exception below:
============================================================================
Fabruary 06, 2015 1:42:21 pm com.google.api.client.googleapis.services.AbstractGoogleClient <init>
warning: Application name is not set. Call Builder#setApplicationName.
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
}, {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
} ],
"message" : "Invalid Value"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1049)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.ccfsz.service.InsertAccountWithJava.createAccount(InsertAccountWithJava.java:81)
at com.ccfsz.service.InsertAccountWithJava.main(InsertAccountWithJava.java:30)
=====================================================================================
Parameters explaination:
SERVICE_ACCOUNT_EMAIL:Generated when i create new Client ID in developer console.
SERVICE_ACCOUNT_PKCS12_FILE_PATH:Generated when i create new Client ID in developer console.
ACCOUNT_TYPE:I provided to google when submit my application.
userToken:I got from the authentication url provided to google.
accountName,authTokenType and authToken is arbitrary String.
2.Before i execute the code above ,do i need to do anything else?
3.I can get google authorization page through (https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/glass.timeline+https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&access_type=offline&approval_prompt=force&include_granted_scopes=true&client_id=540223414844-jjhqevuu0rhmoa3u6gkd05g7v29i89kk.apps.googleusercontent.com&redirect_uri=http://www.eyenotes.com/glass/login.php) using web application .how can i get this page and get permission using service account.
4.Who can give me any hint ? Sometimes,after execute test code above,i got nothing.in this case,according to their source code , this means i got a Http response code between 200 and 300, but i never get Accounts on my glass device which accountType equals "com.eyenotes".sometimes it return 400 with the excepiton above.
who have any idea,please tell me.I am very appreciate.
The userToken may not be the same every single time. Instead of hard-coding it to a String, I would get the token sent to your sign-in page during the authentication process.
Also, the error says you will need to call setApplicationName(String) on your Mirror object in the following code:
Mirror service = new Mirror.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
Refer to line 38 here.
I was testing the authentication for my GDK Glassware :
This is my code:
===================================================================================
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Lists;
import com.google.api.services.mirror.Mirror;
import com.google.api.services.mirror.model.Account;
import com.google.api.services.mirror.model.AuthToken;
public class InsertAccountWithJava {
/** Email of the Service Account */
private static final String SERVICE_ACCOUNT_EMAIL =
"540223414844-tj91ijj3u9**********#developer.gserviceaccount.com ";
/** Path to the Service Account's Private Key file */
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH =
"C:/Users/Yuan/Desktop/eyenotes-847a787fecec.p12";
/** The account type, usually based on your company or app's package. */
private static final String ACCOUNT_TYPE = "com.myapplication";
/** The Mirror API scopes needed to access the API. */
private static final List<String> MIRROR_ACCOUNT_SCOPES =Arrays.asList(
"https://www.googleapis.com/auth/glass.thirdpartyauth");
public static void main(String[] args) {
try {
Mirror mirror = getMirrorService();
createAccount(mirror, "6164da1******", "zhongmeiCM", "com.myapplication", "747dab3e60dd8cd45595767580040538c8a29fcf");
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
/**
* Build and returns a Mirror service object authorized with the service accounts.
*
* #return Mirror service object that is ready to make requests.
*/
public static Mirror getMirrorService() throws GeneralSecurityException, IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(MIRROR_ACCOUNT_SCOPES)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Mirror service = new Mirror.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
/**
* Creates an account and causes it to be synched up with the user's Glass.
* This example only supports one auth token; modify it if you need to add
* more than one, or to add features or user data or the password field.
*
* #param mirror the service returned by getMirrorService()
* #param userToken the user token sent to your auth callback URL
* #param accountName the account name for this particular user
* #param authTokenType the type of the auth token (chosen by you)
* #param authToken the auth token
*/
public static void createAccount(Mirror mirror, String userToken, String accountName,
String authTokenType, String authToken) {
try {
Account account = new Account();
List<AuthToken> authTokens = Lists.newArrayList();
AuthToken authToken1 = new AuthToken().setType(authTokenType).setAuthToken(authToken);
authTokens.add(authToken1);
account.setAuthTokens(authTokens);
account.setPassword("123456");
mirror.accounts().insert(
userToken, ACCOUNT_TYPE, accountName, account).execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}
=====================================================================================
But I get an exception:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
}, {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
} ],
"message" : "Invalid Value"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1049)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at TestInsert.createAccount(TestInsert.java:92)
at TestInsert.main(TestInsert.java:39)
Question 1.please tell me how to generate the parameter:authToken,and what's the difference between authToken and accessToken ?
Question 2.what's the problem with my test code ? When can i get the Exception above.
authToken is an arbitrary String that you can define yourself. accessToken, on the other hand, is a token given to you during the authentication process. It is passed to the Google Mirror API to give your application access to user data.
Refer to the selected answer to this post.
I had written a java program which uses client id and client secret for authentication. When i run my program it gives an url and when i go to that url it gives me access token. How can i programatically get the access token without using a browser?
My code:
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.admin.directory.Directory;
import com.google.api.services.admin.directory.DirectoryScopes;
import com.google.api.services.admin.directory.model.User;
import com.google.api.services.admin.directory.model.Users;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class DirectoryCommandLine {
private static String CLIENT_ID = "YOUR_CLIENT_ID";
private static String CLIENT_SECRET = "YOUR_CLIENT_SECRET";
private static String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
public static void main(String[] args) throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, Arrays.asList(DirectoryScopes.ADMIN_DIRECTORY_USER))
.setAccessType("online")
.setApprovalPrompt("auto").build();
String url = flow.newAuthorizationUrl().setRedirectUri(REDIRECT_URI).build();
System.out.println("Please open the following URL in your browser then type the authorization code:");
System.out.println(" " + url);
System.out.println("Enter authorization code:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String code = br.readLine();
GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(REDIRECT_URI).execute();
GoogleCredential credential = new GoogleCredential().setFromTokenResponse(response);
// Create a new authorized API client
Directory service = new Directory.Builder(httpTransport, jsonFactory, credential)
.setApplicationName("DirectoryCommandLine")
.build();
List<User> allUsers = new ArrayList<User>();
Directory.Users.List request = service.users().list().setCustomer("my_customer");
// Get all users
do {
try {
Users currentPage = request.execute();
allUsers.addAll(currentPage.getUsers());
request.setPageToken(currentPage.getNextPageToken());
} catch (IOException e) {
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
} while (request.getPageToken() != null &&
request.getPageToken().length() > 0 );
// Print all users
for (User currentUser : allUsers) {
System.out.println(currentUser.getPrimaryEmail());
}
}
}
You do need to use a browser to get user's authorization, but you only have to do it exactly once if you store your refresh token securely.
What's your scenario? You can use embedded browser in mobile, and get the authorization code automatically.
I would like to implement push notifications for my website (obviously only in compatible browser as Safari 7).
I have read the Apple documentation and I have successfully created my package containing my icon.iconset, my certificate.p12, manifest.json and a website.json.
Now I would like to ask the permission to the user when I first visit the website. If he allows it, I should send the package.
Everything is pretty clear but I don't know how to go on.
How do I create my push package out of my files? How do I precisely sign it? The package should be always the same so I could sign it on my mac and upload to my server only one package.
If you have experience with this technology, please let me know :)
I have successfully create push package to ask permission on safari web push notifications using REST API in java. Also I have follow steps which provide by Apple officials on there sites.
Please follow below steps to create push package.
Create your web push notification P12 certificate from your apple account.
Create your REST API using https for pushPackage which contain icon.iconset, your certificate.p12, manifest.json and a website.json. p12 certificate must be web push notification certificate.
How to create push package:- Please refer below java code. I have create push package using java servlet. which provide 2 web service end points.
v1/pushpackage/webpushID
v1/log
Servlet which process your push package request which send by safari push notification method
SafariPushPakageAPI.java
/*
Push Package REST API handler
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import com.safari.Packager;
public class SafariPushPakageAPI extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
public static String ServerPath = null;
private static final String REQUEST_PERMISSION = "/v1/pushPackages/YOUR_WEB_PUSH_ID";
private static final String REQUEST_ERRORLOG = "/v1/log";
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doRequest(request, response);
}
// /v1/pushPackages/webpushID
// /v1/log
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doRequest(request, response);
}
private void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("===>> SAFARI PUSH NOTIFICATION REQUEST");
String path = request.getPathInfo();
System.out.println("PATH ===>> "+path);
if(path == null){
doRequestPermission(request, response);
}else if (path.equalsIgnoreCase(REQUEST_PERMISSION)){
doRequestPermission(request, response);
}else if (path.equalsIgnoreCase(REQUEST_ERRORLOG)){
doRequestShowErrorLog(request, response);
}else{
doRequestPermission(request, response);
}
}
private void doRequestPermission(HttpServletRequest request,HttpServletResponse response) {
try{
System.out.println("INSIDE REQUEST PERMISSION ==>>>");
System.out.println(IOUtils.toString(request.getReader()));
String authToken = StringUtils.isBlank(request.getParameter("token")) ? "UserTokenRT124DFGH" : StringUtils.trimToEmpty(request.getParameter("token"));
System.out.println("=>>>>>>>>>> USER TOKEN =>>>>>>>>>> "+authToken);
#SuppressWarnings("deprecation")
String packagePath =request.getRealPath("pushPackage.raw/icon.iconset/"); // LOCATION WHERE YOUR PUSH PACKAGE FOLDER CONTAIN LOGOS AND website.json file
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=\"pushpackage.zip\"");
OutputStream out = response.getOutputStream();
out.write(Packager.createPackageFile(authToken,packagePath));
response.flushBuffer();
}catch(IOException ioe){
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void doRequestShowErrorLog(HttpServletRequest request,HttpServletResponse response) {
try{
System.out.println("ERROR LOG STARTED");
System.out.println(IOUtils.toString(request.getReader()));
System.out.println("END");
}catch(Exception e){
e.printStackTrace();
}
}
}
Packager.java
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONObject;
/**
*
* #author Ritesh
*/
public class Packager {
final static String CERTIFICATE_PATH="PATH TO YOUR 12 CERTIFICATE";
final static String CERTIFICATE_PASS="PASSWORD";
static String getJSON(String authenticationToken) throws Exception {
JSONObject obj = new JSONObject();
obj.put("websiteName", "WEB SITE NAME");
obj.put("websitePushID", "WEB PUSH ID");
obj.put("allowedDomains", new JSONArray());
obj.getJSONArray("allowedDomains").put("https://TEST.EXAMPLE.net");//LIST OF DOMAINS ALLOW
obj.put("urlFormatString", "https://TEST.EXAMPLE.net/%#");
obj.put("authenticationToken", authenticationToken);
obj.put("webServiceURL", "https://API.EXAMPLE.COM");//callback URL WITHOUT WEB SERVICE ENDPOINT NAME
return obj.toString();
}
public static byte[] createPackageFile(String authenticationToken, String path) throws Exception {
System.out.println("packaging safari file with token: " + authenticationToken);
ZipHandler zip = new ZipHandler();
File dir = new File(path);
for (File file : dir.listFiles()) {
InputStream is = new FileInputStream(file);
byte[] bytes = IOUtils.toByteArray(is);
zip.addFile("icon.iconset", file.getName(),bytes );
}
zip.addFile("", "website.json", getJSON(authenticationToken).getBytes());
byte[] manifest = zip.manifest();
zip.addFile("", "manifest.json", manifest);
zip.addFile("", "signature", sign(manifest));
return zip.getBytes();
}
static byte[] sign(byte bytesToSign[]) throws Exception {
return new PKCS7Signer().sign(CERTIFICATE_PATH,CERTIFICATE_PASS, bytesToSign);
}
/**
* Servlet handler , should listen on the callback URL (as in webServiceURL)
* #param requestPath
* #param req
* #param servletRequest
* #param servletResponse
* #throws Exception
*/
public static void main(String[] args) throws Exception {
Packager.createPackageFile("SafriNotifcation","");
}
}
PKCS7Signer.java which create your signature file.
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.Store;
public final class PKCS7Signer {
static {
try{
Security.addProvider(new BouncyCastleProvider());
}catch(Exception e){
e.printStackTrace();
}
}
private KeyStore getKeystore(String storeLocation, String storePasswd) throws Exception {
if (storeLocation == null) {
System.out.println("Could not find store file (.p12)");
return null;
}
// First load the keystore object by providing the p12 file path
KeyStore clientStore = KeyStore.getInstance("PKCS12");
// replace testPass with the p12 password/pin
clientStore.load(new FileInputStream(storeLocation), storePasswd.toCharArray());
return clientStore;
}
private X509CertificateHolder getCert(KeyStore keystore, String alias) throws Exception {
java.security.cert.Certificate c = keystore.getCertificate(alias);
return new X509CertificateHolder(c.getEncoded());
}
private PrivateKey getPrivateKey(KeyStore keystore, String alias, String storePasswd) throws Exception {
return (PrivateKey) keystore.getKey(alias, storePasswd.toCharArray());
}
public byte[] sign(String storeLocation, String storePasswd, byte[] dataToSign) throws Exception {
KeyStore clientStore = getKeystore(storeLocation, storePasswd);
if (clientStore == null) {
return null;
}
Enumeration aliases = clientStore.aliases();
String alias = "";
while (aliases.hasMoreElements()) {
alias = (String) aliases.nextElement();
if (clientStore.isKeyEntry(alias)) {
break;
}
}
CMSTypedData msg = new CMSProcessableByteArray(dataToSign); // Data to sign
X509CertificateHolder x509Certificate = getCert(clientStore, alias);
List certList = new ArrayList();
certList.add(x509Certificate); // Adding the X509 Certificate
Store certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// Initializing the the BC's Signer
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(
getPrivateKey(clientStore, alias, storePasswd));
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder()
.setProvider("BC").build()).build(sha1Signer, x509Certificate));
// adding the certificate
gen.addCertificates(certs);
// Getting the signed data
CMSSignedData sigData = gen.generate(msg, false);
return sigData.getEncoded();
}
}
please note used latest bouncy castle jars for create signature file
bcprov-jdk15on-157.jar
bcpkix-jdk15on-157.jar
Write your javascript on your client side page.it contains simple java script to get permissions.
///
// For safari
var domain="YOUR WEB PUSH ID";
function safariIniti() {
var pResult = window.safari.pushNotification.permission(domain);
if(pResult.permission === 'default') {
//request permission
requestPermissions();
} else if (pResult.permission === 'granted') {
console.log("Permission for " + domain + " is " + pResult.permission);
var token = pResult.deviceToken;
// Show subscription for debug
console.log('Subscription details:'+token);
} else if(pResult.permission === 'denied') {
console.log("Permission for " + domain + " is " + pResult.permission);
}
}
function getToken(){
// always start with a letter (for DOM friendlyness)
var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65));
do {
// between numbers and characters (48 is 0 and 90 is Z (42-48 = 90)
var ascicode=Math.floor((Math.random()*42)+48);
if (ascicode<58 || ascicode>64){
// exclude all chars between : (58) and # (64)
idstr+=String.fromCharCode(ascicode);
}
} while (idstr.length<32);
return (idstr);
}
function requestPermissions() {
var tokenVal = getToken();
window.safari.pushNotification.requestPermission('WEb service url without end points',domain,{token:tokenVal},
function(subscription) {
console.log(subscription.permission);
console.log("PERMISSION ====>> "+subscription.permission);
if(subscription.permission === 'granted') {
//TODO
}
else if(subscription.permission === 'denied') {
// TODO:
}
});
}
Apple provides a php file that you can use to create your push package including the signature. https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/CompanionFile.zip
Alternatively, you can use the push_package gem, https://github.com/SymmetricInfinity/push_package, which we developed when implementing safari push notifications for zeropush.com. More details are available at https://zeropush.com/blog/implementing-safari-push-notifications-in-osx-mavericks.
Follow this apple documentation and github repo, they include sufficient information required to create a safari push notifications.