how to Authenticate emails to open google sheet v4 in java example - java

I created a google sheet by google api service v4 in java. I am trying to Authenticate emails (Users) which can open google sheet. Say, I have 4 email ids:
abc#gmail.com
123#gmail.com
324#gmail.com
xyz#gmail.com
these all 4 users can open the google sheet.
I have wrote a code below, please help me to rectify this problem
public static void insertDataInSheet(String spreadsheetId){
System.out.print("sheet id : >> "+spreadsheetId);
String range = "Sheet1!A2:E20";
try{
Quickstart.authorize();
Sheets service = getSheetsService();
List<Object> temp = new ArrayList();
temp.add("HHHHHHNN");
temp.add("ON");
temp.add("04/09/2017");
temp.add("500305");
temp.add("2399400");
List<Object> temp1 = new ArrayList();
temp1.add("bata");
temp1.add("OFF");
temp1.add("02/09/2017");
temp1.add("1203994");
temp1.add("5536771");
List<List<Object>> values = Arrays.asList(temp,temp1);
List<ValueRange> data = new ArrayList<ValueRange>();
data.add(new ValueRange().setRange(range).setValues(values));
System.out.println(">>>>>>>>>>>");
BatchUpdateValuesRequest body = new BatchUpdateValuesRequest()
.setValueInputOption("USER_ENTERED")
.setData(data);
BatchUpdateValuesResponse result =service.spreadsheets().values().batchUpdate(spreadsheetId, body).execute();
}catch(Exception ex){
ex.printStackTrace();
}
}

Related

Fetching a user's "other" Google contacts in Android

If I understand correctly, in order to fetch the user Google contacts from my Android app, I should use the People API instead of the Contacts API. In my case, I want to get all user's contacts including the "other contacts", as shown in the figure below (one can see his/her other contacts by clicking on the other contacts link):
Up to now, I have successfully used the People API as shown below. First I provide the required scopes to the Google SignIn Options:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestServerAuthCode(getString(R.string.default_web_client_id))
.requestEmail()
.requestProfile()
.requestScopes(new Scope(PeopleServiceScopes.CONTACTS_READONLY))
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
Then I use my webclient Id and secret to fetch the user's contacts:
public void getUserContacts () throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
// Go to the Google API Console, open your application's
// credentials page, and copy the client ID and client secret.
// Then paste them into the following code.
String clientId = getString(R.string.webClientIDAutoCreated);
String clientSecret = getString(R.string.webClientIDSecretAutoCreated);
// Or your redirect URL for web based applications.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
String scope = "https://www.googleapis.com/auth/contacts.readonly";
String serverAuthCode = userSettings.getString(USER_PREFS_SERVER_AUTH_CODE,"");
// Step 1: Authorize -->
String authorizationUrl = new GoogleBrowserClientRequestUrl(clientId, redirectUrl, Arrays.asList(scope)).build();
// Point or redirect your user to the authorizationUrl.
System.out.println("Go to the following link in your browser:");
System.out.println(authorizationUrl);
// Read the authorization code from the standard input stream.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("What is the authorization code?");
String code = in.readLine();
// End of Step 1 <--
// Step 2: Exchange -->
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(httpTransport, jsonFactory, clientId, clientSecret, serverAuthCode, redirectUrl).execute();
// End of Step 2 <--
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setFromTokenResponse(tokenResponse);
PeopleService peopleService = new PeopleService.Builder(httpTransport, jsonFactory, credential)
.setApplicationName(getString(R.string.app_name))
.build();
ListConnectionsResponse response = peopleService.people().connections()
.list("people/me")
.setPersonFields("names,emailAddresses")
.execute();
// Print display name of connections if available.
List<Person> connections = response.getConnections();
if (connections != null && connections.size() > 0) {
for (Person person : connections) {
List<Name> names = person.getNames();
if (names != null && names.size() > 0) {
myLog(TAG,DEBUG_OK,"Name: " + person.getNames().get(0).getDisplayName());
List<EmailAddress> emailAddresses = person.getEmailAddresses();
if (emailAddresses != null && emailAddresses.size() > 0) {
for (EmailAddress email: emailAddresses)
myLog(TAG,DEBUG_OK,"email: " + email.getValue());
}
}
else {
myLog(TAG,DEBUG_OK,"No names available for connection.");
}
}
}
else {
System.out.println("No connections found.");
}
}
I was hoping that this would get all available contacts, however it returns only a small subset. So my question is whether I need to pass / use any other scopes to read all contacts, including the "other contacts" list.
The People API doesn't appear to support the "Other Contacts" contacts as described in this answer. You should use the Contacts API to get the data you want.
People API allows to fetch other Contacts now as described here
https://developers.google.com/people/v1/other-contacts
ListOtherContactsResponse response = peopleService.otherContacts().list()
.setReadMask("metadata,names,emailAddresses")
.execute();
List<Person> otherContacts = response.getOtherContacts();

Listing public folders

I'm writing a program for importing contacts from an ERP system to Outlook. Different emails will receive different lists of contacts from ERP. The idea here is, in each email I have a public contact folder that can be accessed by a technical user. The technical user can write contacts into this folder. Here is the code for searching the folder:
protected FolderId findFolderId(String folderDisplayName, String userEmail) throws Exception {
Mailbox userMailbox = new Mailbox(userEmail);
FolderId contactRootFolder = new FolderId(WellKnownFolderName.Root, userMailbox);
FolderId result = null;
FolderView view = new FolderView(Integer.MAX_VALUE);
view.setPropertySet(new PropertySet(BasePropertySet.IdOnly, FolderSchema.DisplayName));
view.setTraversal(FolderTraversal.Deep);
FindFoldersResults findFolderResults = this.service.findFolders(contactRootFolder, view);
//find specific folder
for (Folder f : findFolderResults) {
if (folderDisplayName.equals(f.getDisplayName())) {
result = f.getId();
}
}
return result;
}
The service object is created as follows:
this.service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials(userName, passWord);
this.service.setCredentials(credentials);
try {
this.service.setUrl(new URI(URL));
} catch (URISyntaxException e) {
LOGGER.error(e);
}
Where URL is the end point for the Exchange server (for Office 365 it is https://outlook.office365.com/EWS/Exchange.asmx).
The code works with Office 2010, I get the Id from that folder, connect to it and save the contacts. After the migration to Office 365, we can't find the public folder. It can just find a folder with the name "PeoplePublicData". (I don't even know that folder exists.)
Throttling in Office365 means your code will only return the first 1000 folder in the Mailbox so if what your looking for isn't within that result set that would be one reason. I would suggest you get rid of
FolderView view = new FolderView(Integer.MAX_VALUE);
and change it to
FolderView view = new FolderView(1000);
and then page the results https://msdn.microsoft.com/en-us/library/office/dn592093(v=exchg.150).aspx which will allow you to get all the Folder in a Mailbox. Also unless you are looking for something in the Non_IPM_Subtree of the Mailbox start the search with MsgFolderRoot eg
FolderId contactRootFolder = new FolderId(WellKnownFolderName.MsgFolderRoot, userMailbox);
That will reduce the number of folders returned.
Also why don't you use a SearchFilter to search for the folder you are after eg https://msdn.microsoft.com/en-us/library/office/dd633627(v=exchg.80).aspx this would eliminate the need to page the results,

Insert row without overwritting data

I end up here a lot from google and since I started trying to make an android app for myself I'm stumped since the v4 API isn't very helpful. I've search on here but I haven't seen an answer that answer my question.
I have a budget spreadsheet. My app is going to grab the data from the sheet and filter it to my current payweek. So I can look at all my current transactions and future ones so I can know how much I have extra to spend. Then I want to just be able to insert a new traction from the app, say if I get gas I want to be able to add that in a couple clicks rather than try to spend a few minutes editing the sheets in the sheet app. Later I plan to customize the formula for the cell I'm putting it in as well as copy it to the cells north and south of it so the math works out.
I used the Android Quickstart to be able to read data easy enough. I've since tweaked that to filter the sheets data to filter my data. I've even gone as far to get it be able to write data to the sheet. The problem is that I can't find any example in java/android in the same style as the quick start to know how to insert a row in the middle of the sheet instead of overwrite the cells. I'm assuming I have to use the INSERTDATAOPTION=INSERT_ROWS somewhere but I can't find anywhere to add it. The documentation suggest I use spreadsheets.values.append but .append never shows up as an option. I only get BatchGet, BatchUpdate, Get, Update.
I'm a beginner and I'm sure my code is clumsy that I've pieced together after hours of googling but I'm sure I'm just missing something easy. Any help would be appreciated.
private List<String> PostDataForApi() throws IOException {
String spreadsheetID = getResources().getString(R.string.my_google_spreadsheet_id);
Integer sheetID = getResources().getInteger(R.integer.my_google_sheet_id);
List<RowData> rowData = new ArrayList<RowData>();
List<CellData> cellData = new ArrayList<CellData>();
String value = "test";
String formula = "=IF(COUNTBLANK(C510) = 2,\"\",Sum(B511+(SUM(C510))))";
String value2 = "999";
CellData cell = new CellData();
cell.setUserEnteredValue(new ExtendedValue().setStringValue(value));
CellData cell2 = new CellData();
cell2.setUserEnteredValue(new ExtendedValue().setFormulaValue(formula));
CellData cell3 = new CellData();
cell3.setUserEnteredValue(new ExtendedValue().setStringValue(value2));
cellData.add(cell);
cellData.add(cell2);
cellData.add(cell3);
rowData.add(new RowData().setValues(cellData));
BatchUpdateSpreadsheetRequest batchRequests = new BatchUpdateSpreadsheetRequest();
BatchUpdateSpreadsheetResponse response;
List<Request> requests = new ArrayList<Request>();
AppendCellsRequest appendCellReq = new AppendCellsRequest();
appendCellReq.setSheetId(sheetID);
appendCellReq.setRows( rowData );
appendCellReq.setFields("userEnteredValue");
requests = new ArrayList<Request>();
requests.add( new Request().setAppendCells(appendCellReq));
batchRequests = new BatchUpdateSpreadsheetRequest();
batchRequests.setRequests( requests );
response = this.mService.spreadsheets().batchUpdate(spreadsheetID, batchRequests).execute();
System.out.println(response.toPrettyString());
return null;
}
I figured it out after some mind numbing throw things against the wall and see what sticks. I had to do it in two steps. The first step will insert a row into your sheet at row 32 so you'll get a blank row 33. Then the second area will insert values into that blank row. I hope this helps someone in the future.
String spreadsheetID = getResources().getString(R.string.my_google_spreadsheet_id);
Integer sheetID = getResources().getInteger(R.integer.my_google_sheet_id);
BatchUpdateSpreadsheetResponse response;
BatchUpdateSpreadsheetRequest batchRequests = new BatchUpdateSpreadsheetRequest();
List<Request> requests = new ArrayList<Request>();
InsertDimensionRequest insertDimensionRequest = new InsertDimensionRequest();
DimensionRange dimRange = new DimensionRange();
dimRange.setStartIndex(32);
dimRange.setEndIndex(33);
dimRange.setSheetId(sheetID);
dimRange.setDimension("ROWS");
insertDimensionRequest.setRange(dimRange);
insertDimensionRequest.setInheritFromBefore(false);
requests.add( new Request().setInsertDimension(insertDimensionRequest));
batchRequests = new BatchUpdateSpreadsheetRequest();
batchRequests.setRequests( requests );
response = this.mService.spreadsheets().batchUpdate(spreadsheetID, batchRequests).execute();
System.out.println(response.toPrettyString());
List<List<Object>> argData = getData(entryTitle, entryValue);
ValueRange vRange = new ValueRange();
vRange.setRange("2016!A33");
vRange.setValues(argData);
List<ValueRange> vList = new ArrayList<>();
vList.add(vRange);
BatchUpdateValuesRequest batchRequest = new BatchUpdateValuesRequest();
batchRequest.setValueInputOption("USER-ENTERED");
batchRequest.setData(vList);
this.mService.spreadsheets().values().batchUpdate(spreadsheetID, batchRequest).execute();
I've been having sooo much unnecessary hustle with the v4 google sheets api, that it was ridiculous. Therefore, I reverted to the gdata (v3) api, much better easier to follow and much better documented also.
Here is the link to setting it up and a few examples https://developers.google.com/google-apps/spreadsheets/
The only thing missing was the authorization process in those notes, which was a hustle, but after some digging I was able to get a authorization code base, as shown below.
public class YourClass {
// Application name
private static final String APPLICATION_NAME = "Your-Application-Name";
// account info and p12
private static final String ACCOUNT_P12_ID = "Get-the-details-developer-console-google";
private static final File P12FILE = new File("D:/path/Drive API Test-bf290e0ee314.p12");
// scopes
private static final List<String> SCOPES = Arrays.asList(
"https://docs.google.com/feeds",
"https://spreadsheets.google.com/feeds");
// Spreadsheet API URL
private static final String SPREADSHEET_URL = "https://spreadsheets.google.com/feeds/spreadsheets/private/full";
private static final URL SPREADSHEET_FEED_URL;
static {
try {
SPREADSHEET_FEED_URL = new URL(SPREADSHEET_URL);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
// Authorize
private static Credential authorize() throws Exception {
System.out.println("authorize in");
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_P12_ID)
.setServiceAccountPrivateKeyFromP12File(P12FILE)
.setServiceAccountScopes(SCOPES)
.build();
boolean ret = credential.refreshToken();
// debug dump
System.out.println("refreshToken:" + ret);
// debug dump
if (credential != null) {
System.out.println("AccessToken:" + credential.getAccessToken());
}
System.out.println("authorize out");
return credential;
}
// Get service
private static SpreadsheetService getService() throws Exception {
System.out.println("service in");
SpreadsheetService service = new SpreadsheetService(APPLICATION_NAME);
service.setProtocolVersion(SpreadsheetService.Versions.V3);
Credential credential = authorize();
service.setOAuth2Credentials(credential);
// debug dump
System.out.println("Schema: " + service.getSchema().toString());
System.out.println("Protocol: " + service.getProtocolVersion().getVersionString());
System.out.println("ServiceVersion: " + service.getServiceVersion());
System.out.println("service out");
return service;
}
From that onward, I was able to perform a number of inserts and appends to the sheets, without any major hustle.

How to get spreadsheets from a specific Google Drive folder?

The code provided in this tutorial (snippet given below) retrieves a list of all the spreadsheets for the authenticated user.
public class MySpreadsheetIntegration {
public static void main(String[] args) throws AuthenticationException,
MalformedURLException, IOException, ServiceException {
SpreadsheetService service = new SpreadsheetService("MySpreadsheetIntegration-v1");
// TODO: Authorize the service object for a specific user (see other sections)
// Define the URL to request. This should never change.
URL SPREADSHEET_FEED_URL = new URL(
"https://spreadsheets.google.com/feeds/spreadsheets/private/full");
// Make a request to the API and get all spreadsheets.
SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL,
SpreadsheetFeed.class);
List<SpreadsheetEntry> spreadsheets = feed.getEntries();
// Iterate through all of the spreadsheets returned
for (SpreadsheetEntry spreadsheet : spreadsheets) {
// Print the title of this spreadsheet to the screen
System.out.println(spreadsheet.getTitle().getPlainText());
}
}
}
But I don't want to get all the spreadsheets. I only want to get those spreadsheets that are in a particular folder (if the folder exists, otherwise terminate the program). Is it possible using this API? If yes, how?
As far as my understanding goes, the SpreadsheetFeed has to be changed. But I didn't get any example snippet against it.
I worked out the solution as follows:
First, get the fileId of that particular folder. Use setQ() to pass query checking for folder and folder name. The following snippet will be useful:
result = driveService.files().list()
.setQ("mimeType='application/vnd.google-apps.folder'
AND title='" + folderName + "'")
.setPageToken(pageToken)
.execute();
Then, get the list of files in that particular folder. I found it from this tutorial. Snippet is as follows:
private static void printFilesInFolder(Drive service, String folderId) throws IOException {
Children.List request = service.children().list(folderId);
do {
try {
ChildList children = request.execute();
for (ChildReference child : children.getItems()) {
System.out.println("File Id: " + child.getId());
}
request.setPageToken(children.getNextPageToken());
} catch (IOException e) {
System.out.println("An error occurred: " + e);
request.setPageToken(null);
}
} while (request.getPageToken() != null &&
request.getPageToken().length() > 0);
}
Lastly, check for spreadsheets and get worksheet feeds for them. The following snippet might help.
URL WORKSHEET_FEED_URL = new URL("https://spreadsheets.google.com/feeds/worksheets/" + fileId + "/private/full");
WorksheetFeed feed = service.getFeed(WORKSHEET_FEED_URL, WorksheetFeed.class);
worksheets = feed.getEntries();

Handling JSON Webhook in JAVA Google App Engine

I am trying to handle a JSON webhook in a Java app that is running in Google App Engine. Right now I am just attempting to post that data into datastore so I can verify it is there.
Here is my current code:
Key storeKey = KeyFactory.createKey("10k", "static");
resp.setContentType("text/plain");
StringBuilder stringBuilder = new StringBuilder(10000);
Scanner scanner = new Scanner(req.getInputStream());
while (scanner.hasNextLine()) {
stringBuilder.append(scanner.nextLine());
}
String body = stringBuilder.toString();
Date date = new Date();
Entity store = new Entity("10k", storeKey);
store.setProperty("Date", date);
store.setProperty("Body", body);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(store);
It works for a normal POST. But it does not work for a JSON webhook.
Any suggestions were to go? So far googling for it hasn't taken me very far.

Categories

Resources