Is there any way to output real time clock values in google sheets? Basically what I'm trying to do is use the values in a cell to create a live Gantt chart that will output the status of the machine based on the time value and the downtime reason the operator used.
There are 2 ways of achieving this. The first is the simplest, =now() gets updated every minute automatically. The second technique is more complex but offers more control, especially if you want to control the precise moment when the clock should get updated.
Easiest way - 20 seconds:
Apply the =NOW() function and change your recalculation setting to "On change and every minute" in your spreadsheet at File > Spreadsheet settings.
Long way - 5 to 30 minutes. Requires a server to execute code every x minutes
Its possible to do this via the API. There are a couple of ways to achieve this, but both involve the API.
1) Create a blank sheet and update the time in any cell using the API. Lets call this sheet universal. Simply inserting "=now()" into a cell will always ensure the time is updated every time an API call is made. Overwrite this cell with "=now()" in every API call. Then use the function : IMPORTRANGE() in any sheet referencing the call value in the universal sheet. This is the preferred option since you only need to create code for one sheet and then you can reference in any other sheet.
2) Same as above, but just write directly to your sheet and cell as opposed to a universal sheet. The disadvantage of this method is if you move cells around you will need to change your code.
Both options will require you to call the API and setting up a scheduled job to run the program every x minutes.
Instructions (JAVA - though you can follow the same logic for other languages). Pretty much most of the below is copied from Google Sheets API guide, I have listed all my steps below:
Step 1: Turn on the Google Sheets API
a Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.
b On the Add credentials to your project page, click the Cancel button.
c At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.
d Select the Credentials tab, click the Create credentials button and select OAuth client ID.
e Select the application type Other, enter the name "Google Sheets API Quickstart", and click the Create button.
f Click OK to dismiss the resulting dialog.
g Click the file_download (Download JSON) button to the right of the client ID.
h Move this file to your working directory and rename it client_secret.json.
Step 2 If using Maven add the following dependencies to your pom file:
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-java6</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.23.0</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-sheets</artifactId>
<version>v4-rev504-1.23.0</version>
</dependency>
Step 3 Copy this class Credentials.java
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
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.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
public class Credentials {
/** Application name. */
private static final String APPLICATION_NAME =
"Google Sheets";
/** Directory to store user credentials for this application. */
private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"), ".credentials/sheets.googleapis.com-java-quickstart");
/** Global instance of the {#link FileDataStoreFactory}. */
private static FileDataStoreFactory DATA_STORE_FACTORY;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY =
JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
/** Global instance of the scopes required by this quickstart.
*
* If modifying these scopes, delete your previously saved credentials
* at ~/.credentials/sheets.googleapis.com-java-quickstart
*/
private static final List<String> SCOPES =
Arrays.asList(SheetsScopes.SPREADSHEETS);
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
/**
* Creates an authorized Credential object.
* #return an authorized Credential object.
* #throws IOException
*/
public static Credential authorize() throws IOException {
// Load client secrets.
InputStream in =
Quickstart.class.getResourceAsStream("/client_secret.json");
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
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;
}
/**
* Build and return an authorized Sheets API client service.
* #return an authorized Sheets API client service
* #throws IOException
*/
public static Sheets getSheetsService() throws IOException {
Credential credential = authorize();
return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
}
Step 4 Copy the class UpdateDate.java below. Change the spreadsheetID with the ID of your spreadsheet. Change the range with your cell ref. I have entered a default value of Sheet1!a1 as an example
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.model.UpdateValuesResponse;
import com.google.api.services.sheets.v4.model.ValueRange;
public class UpdateDate {
public static void main(String[] args) throws IOException{
Sheets service = Credentials.getSheetsService();
String spreadsheetId = "YOUR_SHEET_ID";
String range = "Sheet1!a1";
#SuppressWarnings("unchecked")
List<List<Object>> values = Arrays.asList(
Arrays.asList(
(Object)"=NOW()"
)
);
ValueRange body = new ValueRange().setValues(values);
UpdateValuesResponse result =
service.spreadsheets().values().update(spreadsheetId, range, body)
.setValueInputOption("USER_ENTERED")
.execute();
}
}
Step 5 Setup a scheduled job to run every x minutes according to your use case. The very first time you run this your browser should open and you will need to click on the accept consent screen. Credentials are then saved locally so thereafter you can run the process via command line without having to click on the consent screen again.
Good Luck!
It looks like you want the NOW function. I don't think sheets supports real time updates, so a volatile function (changes when the sheet is updated) is the best you can do.
Related
I'm building a prototype using Vaadin8 starting from a single-module template.
I'm trying to assign a unique UI instance (a session) to each authenticated user, so that each user is presented with a particular type of content according to their own settings within the app. Here's my configuration:
#WebListener
public class Market implements ServletContextListener {
public static ArrayList<User>users;
public void contextInitialized(ServletContextEvent sce) {
users=new ArrayList<User>();
User hau=new User("hau");
users.add(hau);
User moc=new User("moc");
users.add(moc);
}
public void contextDestroyed(ServletContextEvent sce){}
}
public class User {
public String username;
public user(String username){this.username=username;}
}
public class MyUI extends UI {
User us3r;
#Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
String username;
if (this.us3r==null) {username="Guest";}else {username=us3r.username;}
Label who=new Label(username);
TextField userfield=new TextField();
Button login=new Button("login");
login.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
for (User user:Market.users) {
if (userfield.getValue().equals(user.username)) {
us3r=user;Page.getCurrent().reload();return;
}
}Notification.show("No user "+userfield.getValue());
}
});
Button logout=new Button("logout");
logout.addClickListener(new ClickListener() {
public void buttonClick(ClickEvent event) {
if(us3r!=null) {us3r=null; Page.getCurrent().reload();}
}
});
layout.addComponent(userfield);
layout.addComponent(login);
layout.addComponent(who);
layout.addComponent(logout);
setContent(layout);
}
After inputting one of the two usernames registered in the Database, I'd like the Label object to display the name of the authenticated user, instead of "Guest". Another effect I'm trying to achieve is if a user is logged in and there is another request to the server, it should generate a fresh UI with the uninstantiated us3r attribute.
Caveats: I have been using Vaadin Flow lately rather than Vaadin 8. So my memory is hazy, and my code may be wrong. And I have kept all the examples overly simple, not ready for production. Lastly, I am sure others would take a different approach, so you may want to do some internet searching to see alternatives.
UI is malleable
The UI of Vaadin is more plastic and malleable than you may realize. You can entirely replace the initial VerticalLayout with some other widget-containing-view.
The way I have handled logins with Vaadin is that my default UI subclass checks for an object of my own User class in the web session. Being based on Jakarta Servlet technology, every Vaadin web app automatically benefits from the Servlet-based session handling provided by the Servlet container. Furthermore, Vaadin wraps those as a VaadinSession.
If the User object is found to be existing as an "attribute" (key-value pair) in the session, then I know the user has already logged-in successfully. So I display the main content in that initial UI subclass object. By "main content", I mean an instance of a particular class I wrote that extends VertialLayout, or HoriontalLayout or some such.
If no User object is found, then my initial UI subclass object displays a login view. By "login view" I mean an instance of some other particular class I wrote that extends VertialLayout, or HoriontalLayout or some such.
When you switch or morph the content within a UI subclass instance, Vaadin takes care of all the updating of the client. The change in state of your UI object on the server made by your Java code is automatically communicated to the Vaadin JavaScript library that was initially installed in the web browser. That Vaadin JS
library automatically renders your changed user-interface by generating the needed HTML, CSS, JavaScript, and so on. There is no need for you to be reloading the page as you seem to be doing in your example code. As a single-page web app, the web page only loads once. In Vaadin, we largely forget about the HTTP Request/Response cycle.
Example app
First we need a simple User class for demonstration purposes.
package work.basil.example;
import java.time.Instant;
import java.util.Objects;
public class User
{
private String name;
private Instant whenAuthenticated;
public User ( String name )
{
Objects.requireNonNull( name );
if ( name.isEmpty() || name.isBlank() ) { throw new IllegalArgumentException( "The user name is empty or blank. Message # b2ec1529-47aa-47c1-9702-c2b2689753cd." ); }
this.name = name;
this.whenAuthenticated = Instant.now();
}
#Override
public boolean equals ( Object o )
{
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
User user = ( User ) o;
return name.equals( user.name );
}
#Override
public int hashCode ( )
{
return Objects.hash( name );
}
}
The starting point of our app, our subclass of UI checks the session and switches content. Notice how we segregated the check-and-switch code to a named method, ShowLoginOrContent. This allows us to invoke that code again after login, and again after logout.
package work.basil.example;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.UI;
import javax.servlet.annotation.WebServlet;
import java.util.Objects;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of an HTML page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {#link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
#Theme ( "mytheme" )
public class MyUI extends UI
{
#Override
protected void init ( VaadinRequest vaadinRequest )
{
this.showLoginOrContent();
}
void showLoginOrContent ( )
{
// Check for User object in session, indicating the user is currently logged-in.
User user = VaadinSession.getCurrent().getAttribute( User.class );
if ( Objects.isNull( user ) )
{
LoginView loginView = new LoginView();
this.setContent( loginView );
} else
{
CustomerListingView customerListingView = new CustomerListingView();
this.setContent( customerListingView );
}
}
#WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
#VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
public static class MyUIServlet extends VaadinServlet
{
}
}
Here is that LoginView, a VerticalLayout. We have our username & password, with a "Sign in" button. Notice how on successful authentication we:
Instantiate a User and add to the automatically-created session as an "attribute" key-value pair. The key is the class User, and the value is the User instance. Alternatively, you can choose to use a String as the key.
Invoke that showLoginOrContent method on MyUI to swap out our login view with a main content view.
In real work, I would locate the user-authentication mechanism to its own class unrelated to the user-interface. But here we ignore the process of authentication for this demonstration.
package work.basil.example;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.*;
public class LoginView extends VerticalLayout
{
private TextField userNameField;
private PasswordField passwordField;
private Button authenticateButton;
public LoginView ( )
{
// Widgets
this.userNameField = new TextField();
this.userNameField.setCaption( "User-account name:" );
this.passwordField = new PasswordField();
this.passwordField.setCaption( "Passphrase:" );
this.authenticateButton = new Button( "Sign in" );
this.authenticateButton.addClickListener( ( Button.ClickListener ) clickEvent -> {
// Verify user inputs, not null, not empty, not blank.
// Do the work to authenticate the user.
User user = new User( this.userNameField.getValue() );
VaadinSession.getCurrent().setAttribute( User.class , user );
( ( MyUI ) UI.getCurrent() ).showLoginOrContent(); // Switch out the content in our `UI` subclass instance.
}
);
// Arrange
this.addComponents( this.userNameField , this.passwordField , this.authenticateButton );
}
}
Lastly, we need our main content view. Here we use a "customer listing" that is not yet actually built. Instead, we place a couple pieces of text so you know the layout is appearing. Notice how in this code we look up the user's name from our User object in the session attribute.
We include a "Sign out" button to show how we reverse the authentication simply by clearing our User instance as the value of our "attribute" on the session. Alternatively, you could kill the entire session by calling VaadinSession::close. Which is appropriate depends on your specific app.
package work.basil.example;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import java.time.Duration;
import java.time.Instant;
public class CustomerListingView extends VerticalLayout
{
Button logoutButton;
public CustomerListingView ( )
{
// Widgets
this.logoutButton = new Button( "Sign out" );
this.logoutButton.addClickListener( ( Button.ClickListener ) clickEvent -> {
VaadinSession.getCurrent().setAttribute( User.class , null ); // Pass null to clear the value.
( ( MyUI ) UI.getCurrent() ).showLoginOrContent();
}
);
User user = VaadinSession.getCurrent().getAttribute( User.class );
Duration duration = Duration.between( user.getWhenAuthenticated() , Instant.now() );
Label welcome = new Label( "Bonjour, " + user.getName() + ". You’ve been signed in for: " + duration.toString() + "." );
Label placeholder = new Label( "This view is under construction. A table of customers will appear here.\"" );
// Arrange
this.addComponents( this.logoutButton , welcome , placeholder );
}
}
The effect of the "Sign out" button is to remove the main content, and take the user back to the login view.
Separation of concerns
One of the aims of the approach to logins is separation of concerns. The concern of building an interactive user-interface (Vaadin widgets and code) should be kept largely separate from the business logic of how we determine if a user is who they claim to be (authentication code).
Our UI subclass knows almost nothing about user-authentication. We moved all the mechanics of logging-in to other non-Vaadin-specific classes. The Vaadin-related code only has two connection points to authentication: (a) Passing collected credentials (username, password, or such), and (b) Checking for the presence of a User object in the session’s key-value store.
Multi-window web apps
By the way, you should know that Vaadin 8 has amazing support for multi-window web apps. You can write links or buttons to open additional windows/tabs in the browser, all working within the same web app and the same user session. Each tab/window has its own instance of a UI subclass you wrote. All of these UI subclass instances share the same VaadinSession object.
So using the logic seen above applies to all such tab/windows: Multiple windows all belonging to one session with one login.
Fake dialog boxes are not secure
You might be tempted to put your login view inside a dialog box appearing over your main content. Do not do this. A web dialog box is “fake”, in that it is not a window created and operated by the operating-system. A web app dialog window is just some graphics to create the illusion of a second window. The pretend dialog and the underlying content are actually all one web page.
A hacker might gain access to the content on the page, and might be able to defeat your login dialog. This is mentioned in the Vaadin manual, on the page Sub-Windows.
In my example above, we have no such security problem. The sensitive main content arrives on the user’s web browser only after authentication completes.
Web app lifecycle hooks
By the way, your use of ServletContextListener is correct. That is the standard hook for the lifecycle of your web app launching. That listener is guaranteed to run before the first user’s request arrives, and again after the last user’s response is sent. This is an appropriate place to configure resources needed by your app in general, across various users.
However, in Vaadin, you have an alternative. Vaadin provides the VaadinServiceInitListener for you to implement. This may be more convenient than the standard approach, though you need to configure it by creating a file to make your implementation available via the Java Service Implementation Interface (SPI) facility. Your VaadinServiceInitListener as another place to setup resources for your entire web app. You can also register further listeners for the service (web app) shutting down, and for user-session starting or stopping.
Browser Reload button
One last tip: You may want to use the #PreserveOnRefresh annotation.
Vaadin Flow
In Vaadin Flow (versions 10+), I take the same approach to logins.
Well, basically the same. In Vaadin Flow, the purpose of the UI class was dramatically revamped. Actually, that class should have been renamed given how differently it behaves. We no longer routinely write a subclass of UI when starting a Vaadin app. A UI instance is no longer stable during the user's session. The Vaadin runtime will replace the UI object by another new instance (or re-initialize it), sometimes quite rapidly, for reasons I do not yet understand. So I do not see much practical use for UI for those of us writing Vaadin apps.
Now in Flow I start with an empty layout, instead of a UI subclass. Inside that layout I swap nested layouts. First the login view. After authentication, I swap the login view for the main content view. On logout, the opposite (or close the VaadinSession object).
I have developed an Atlasian Bitbucket plugin which globally listens for push/PR and send repository details to databases using REST API.
I need to configure REST API URL and credential so that my plugin can make an API call. Currently I have hardcoded REST API URL and credential in my plugin properties file. Which I don't like because every time if I need to create a package to target my test environment or production, I have to change. Also, I don't like to keep credentials in the source code.
What is the best way to add configuration screen in the bitbucket plugin? I would like to have form for URL, username and password (once I installed the plugin) and update the storage in Bitbucket only once. If I need to restart my bitbucket, I do not want to lose saved data.
I tried to search on how to configure a bitbucket plugin, however I could not find an easy way. I do see multiple approaches, for example to add "Configure" button which will open a servelet to take user input. Seems very cryptic to me. Also, I see so many recommendations for template, for example velocity, soy etc which confused me a lot.
Since I am new to plugin development therefore not able to explore. Looking for some help.
I have solution for this case:
From pom.xml please add more library:
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-core</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
Create new abc-server.properties on resources/ folder with following content:
server.username=YOUR_USERNAME
server.password=YOUR_PASSWORD
Get value from abc-server.properties on service class as the following:
import com.atlassian.plugin.util.ClassLoaderUtils;
...
final Properties p = new Properties();
final InputStream is = ClassLoaderUtils.getResourceAsStream("abc-server.properties", this.getClass());
try {
if (is != null) {
p.load(is);
String username = p.getProperty("server.username");
String password = p.getProperty("server.password");
}
} catch (IOException e) {
e.printStackTrace();
}
Please try to implement it. Thanks!
One possibility for a simple configuration file, is to read somefile.properties from the Bitbucket home directory, this way the config file will survive application updates.
Create somefile.properties in BITBUCKET_HOME
server.username=YOUR_USERNAME
server.password=YOUR_PASSWORD
Read the properties in your plugin class like this
// imports
import com.atlassian.bitbucket.server.StorageService;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
private final StorageService storageService;
// StorageService injected via constructor injection
public SomePlugin(#ComponentImport final StorageService storageService) {
this.storageService = storageService;
}
Properties p = new Properties();
File file = new File(storageService.getHomeDir().toString(), "somefile.properties");
FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream(file);
p.load(fileInputStream);
String username = p.getProperty("server.username");
String password = p.getProperty("server.password");
} catch (IOException e) {
//handle exception
}
I am able to call a number with following code from the link
https://www.twilio.com/docs/api/voice/making-calls
Is it possible to enable dual channel recording with following code ?. if yes, how ?
SDK Version: 6.x 7.x
// Install the Java helper library from twilio.com/docs/java/install
import java.net.URI;
import java.net.URISyntaxException;
import com.twilio.Twilio;
import com.twilio.rest.api.v2010.account.Call;
import com.twilio.type.PhoneNumber;
public class Example {
// Find your Account Sid and Token at twilio.com/user/account
public static final String ACCOUNT_SID = "ACd6b6b7dc8ae6f3e6f7ff72c8dbbd457f";
public static final String AUTH_TOKEN = "your_auth_token";
public static void main(String[] args) throws URISyntaxException {
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
Call call = Call.creator(new PhoneNumber("+14155551212"), new PhoneNumber("+15017250604"),
new URI("http://demo.twilio.com/docs/voice.xml")).create();
System.out.println(call.getSid());
}
}
Twilio developer evangelist here.
You are missing the parameter to record the call in your API call here. When building the call object you need something like the following:
Call call = Call.creator(
new PhoneNumber("+14155551212"),
new PhoneNumber("+15017250604"),
new URI("https://example.com/voice")
)
.setRecord(true)
.setRecordingChannels("dual")
.setRecordingStatusCallback("https://example.com/recording")
.create();
The URL that you pass to the call creator should point at an application that you control as well. This application needs to return TwiML that will connect the first call to another to give you the two legs to record. You need to use <Dial> with either <Number>, <Client>, <Sip> or <Sim>. Like this:
<Response>
<Dial>
<Number>NUMBER TO CONNECT TO</Number>
</Dial>
</Response>
Let me know if this helps at all.
I'm trying to make a call to a number using the Twilio service using a Trial Account.
I'm following the Java example here: https://www.twilio.com/docs/quickstart/java/rest/call-request
I've configured the example with my API credentials, the provided Twilio number, the destination number and the TwiML instructions url.
When I run the MakeCall class the destination number get called.
When I respond to the call I get the "trial account" message, then it asks me to press any key. When I press a key the call is dropped.
As I can see the TwiML instructions url is not called by Twilio.
I've tested also with the Test Credentials with no success.
Any idea on why the TwiML instructions url is not called?
Using the twilio-java helper library and following code from the docs you mentioned above:
We then instantiate a new client object, set the request method to
'POST', fill in the 'From', 'To' and 'Url' parameters in an
associative array, and fire off the request to Twilio!
Aside from any potential issues with your URL...did you also set the request method to POST while configuring your twilio number in the console?
import java.util.Map;
import java.util.HashMap;
import com.twilio.sdk.TwilioRestClient;
import com.twilio.sdk.TwilioRestException;
import com.twilio.sdk.resource.instance.Account;
import com.twilio.sdk.resource.instance.Call;
import com.twilio.sdk.resource.factory.CallFactory;
public class MakeCall {
public static final String ACCOUNT_SID = "AC123";
public static final String AUTH_TOKEN = "456bef";
public static void main(String[] args) throws TwilioRestException {
TwilioRestClient client = new TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN);
Account mainAccount = client.getAccount();
CallFactory callFactory = mainAccount.getCallFactory();
Map<String, String> callParams = new HashMap<String, String>();
callParams.put("To", "5105551212"); // Replace with your phone number
callParams.put("From", "(510) 555-1212"); // Replace with a Twilio number
callParams.put("Url", "http://demo.twilio.com/welcome/voice/"); // Configure your own URL with TwiML instructions using TwiML Bins
// Make the call
Call call = callFactory.create(callParams);
// Print the call SID (a 32 digit hex like CA123..)
System.out.println(call.getSid());
}
}
On the following link there is code which should access the Google Calendar api using OAuth 2.0. Unfortunately it uses the Draft 10 Client Library which is apparently deprecated.
https://developers.google.com/google-apps/calendar/instantiate
The latest Client Library is google-api-java-client-1.12.0-beta. From what I can make out things have changed a lot since the Draft 10 Client Library and I can't work out how to rewrite this code for the current Client Library.
The deprecated code is shown below.
import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessProtectedResource;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant;
import com.google.api.client.googleapis.auth.oauth2.draft10.GoogleAuthorizationRequestUrl;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.calendar.Calendar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
...
public void setUp() throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
// The clientId and clientSecret are copied from the API Access tab on
// the Google APIs Console
String clientId = "YOUR_CLIENT_ID";
String clientSecret = "YOUR_CLIENT_SECRET";
// Or your redirect URL for web based applications.
String redirectUrl = "urn:ietf:wg:oauth:2.0:oob";
String scope = "https://www.googleapis.com/auth/calendar";
// Step 1: Authorize -->
String authorizationUrl = new GoogleAuthorizationRequestUrl(clientId, redirectUrl, 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 -->
AccessTokenResponse response = new GoogleAuthorizationCodeGrant(httpTransport, jsonFactory,
clientId, clientSecret, code, redirectUrl).execute();
// End of Step 2 <--
GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(
response.accessToken, httpTransport, jsonFactory, clientId, clientSecret,
response.refreshToken);
Calendar service = new Calendar(httpTransport, accessProtectedResource, jsonFactory);
service.setApplicationName("YOUR_APPLICATION_NAME");
...
}
...
Can anyone tell how to rewrite this code so it works with the current Client Library?
You can have a look at the documentation of the Google Drive API, which is up to date:
https://developers.google.com/drive/credentials
Then it shouldn't be hard to replace the Drive scope with the Calendar scope and to instantiate the correct Calendar class for the service instead of a Drive service object.
If that situation happens again, the best to be sure you can find the latest version of code samples is to have a look directly on the website of the Google APIs Client Library for Java. You can have a look at it's wiki about auth but also have a look at the sample apps which they make sure are compiling and working with he latest version of the library (it's just harder to keep all the docs up to date sometimes)