Though developers are quite comfortable thinking in abstractions, we still find a lot of value in code examples and fully developed sample applications. Judging by the volume of comments, tweets, and git checkouts of the Au-to-do sample code we released a few weeks ago, our readers agree.
For Google Apps API developers who want to get started writing mobile apps, here’s a great new resource: a sample application that integrates Google Calendar API v3 with Android and illustrates best practices for OAuth 2.0. This meeting scheduler app built by Alain Vongsouvanh gets the user’s contact list, lets users select attendees, and matches free/busy times to suggest available meeting times. It provides a simple Android UI for user actions such as attendee selection:
The sample code for Meeting Scheduler demonstrates many key aspects of developing with Google Apps APIs. After authorizing all required access using OAuth 2.0, the Meeting Scheduler makes requests to the Calendar API. For example, the class FreeBusyTimesRetriever queries the free/busy endpoint to find available meeting times:
FreeBusyTimesRetriever
FreeBusyRequest request = new FreeBusyRequest(); request.setTimeMin(getDateTime(startDate, 0)); request.setTimeMax(getDateTime(startDate, timeSpan)); for (String attendee : attendees) { requestItems.add(new FreeBusyRequestItem().setId(attendee)); } request.setItems(requestItems); FreeBusyResponse busyTimes; try { Freebusy.Query query = service.freebusy().query(request); // Use partial GET to retrieve only needed fields. query.setFields("calendars"); busyTimes = query.execute(); // ... } catch (IOException e) { // ... }
In this snippet above, note the use of a partial GET request. Calendar API v3, along with many other new Google APIs, provides partial response with GET and PATCH to retrieve or update only the data fields you need for a given request. Using these methods can help you streamline your code and conserve system resources.
For the full context of all calls that Meeting Scheduler makes, including OAuth 2.0 flow and the handling of expired access tokens, see Getting Started with the Calendar API v3 and OAuth 2.0 on Android. The project site provides all the source code and other resources, and there’s a related wiki page with important configuration details.
We hope you’ll have a look at the sample and let us know what you think in the Google Apps Calendar API forum. You’re welcome to create a clone of the source code and do some Meeting Scheduler development of your own. If you find a bug or have an idea for a feature, don’t hesitate to file it for evaluation.
All developers agree that saving bandwidth is a critical factor for the success of a mobile application. Less data usage means faster response times and also lower costs for the users as the vast majority of mobile data plans are limited or billed on a per-usage basis.
When using any of the Google Data APIs in your application, you can reduce the amount of data to be transferred by requesting gzip-encoded responses. On average, the size of a page of users returned by the Provisioning API (100 accounts) is about 100 Kb, while the same data, gzip-encoded, is about 5 Kb -- 20 times smaller! When you can reduce data sizes at this dramatic scale, the benefits of compression will often outweigh any costs in client-side processing for decompression.
Enabling gzip-encoding in your application requires two steps. You have to edit the User-Agent string to contain the value gzip and you must also include an Accept-Encoding header with the same value. For example:
User-Agent
gzip
Accept-Encoding
User-Agent: my application - gzip Accept-Encoding: gzip
Client libraries for the various supported programming languages make enabling gzip-encoded responses even easier. For instance, in the .NET client library it is as easy as setting the boolean UseGZip flag of the RequestFactory object:
service.RequestFactory.UseGZip = true;
For any questions, please get in touch with us in the respective forum for the API you’re using.
Users of the Google Documents List API have traditionally had to perform individual export operations in order to export their documents. This is quite inefficient, both in terms of time and bandwidth for these operations.
To improve latency for these operations, we have added the Archive Feed to the API. Archives allow users to export a large number of items at once, in single ZIP archives. This feature provides a useful optimization for users, greatly increasing the efficiency of export operations. Additionally, users can receive emails about archives, and choose to download them from a link provided in the email.
This feature had a soft release earlier this year, and we think it’s now ready for prime time. For more information, please see the Archive Feed documentation.
Since 1998, when the first doodle was released, they have been one of the most loved features of the Google home page. There have been doodles to celebrate all kinds of events, including national holidays, birthdays of artists and scientists, sports competitions, scientific discoveries and even video games! Also, doodles have evolved from simple static images to complex applications, such as the interactive electric guitar used to celebrate the birthday of Les Paul.
Want your company logo to change for selected events or holidays, just like doodles? The Admin Settings API allows domain administrators to write scripts to programmatically change the logo of their Google Apps domain, and Google App Engine offers the ability to configure regularly scheduled tasks, so that those scripts can run automatically every day.
With these two pieces combined, it is pretty easy to implement a complete solution to change the domain logo on a daily basis (assuming the graphic designers have prepared a doodle for each day), as in the following screenshot:
Let’s start with a Python App Engine script called doodleapps.py:
doodleapps.py
import gdata.apps.adminsettings.service from google.appengine.ext import webapp from google.appengine.ext.webapp import util from datetime import date class DoodleHandler(webapp.RequestHandler): # list of available doodles DOODLES = { '1-1': 'images/newyearsday.jpg', '2-14': 'images/valentinesday.jpg', '10-31': 'images/halloween.jpg', '12-25': 'images/christmas.jpg' } # returns the path to the doodle corresponding to the date # or None if no doodle is available def getHolidayDoodle(self, date): key = '%s-%s' % (date.month, date.day) if key not in self.DOODLES: return None return self.DOODLES[key] # handles HTTP requests by setting today’s doodle def get(self): doodle = self.getHolidayDoodle(date.today()) self.response.out.write(doodle) if doodle: service = gdata.apps.adminsettings.service.AdminSettingsService() // replace domain, email and password with your credentials // or change the authorization mechanism to use OAuth service.domain = 'MYDOMAIN.COM' service.email = 'ADMIN@MYDOMAIN.COM' service.password = 'MYPASSWORD' service.source = 'DoodleApps' service.ProgrammaticLogin() # reads the doodle image and update the domain logo doodle_bytes = open(doodle, "rb").read() service.UpdateDomainLogo(doodle_bytes) # webapp initialization def main(): application = webapp.WSGIApplication([('/', DoodleHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()
The script uses a set of predefined doodles which can be edited to match your list of images or replaced with more sophisticated logic, such as using the Google Calendar API to get the list of holidays in your country.
Every time the script is triggered by an incoming HTTP request, it will check whether a doodle for the date is available and, if there is one, update the domain logo using the Admin Settings API.
In order for this script to be deployed on App Engine, you need to to configure the application by defining a app.yaml file with the following content:
app.yaml
application: doodleapps version: 1 runtime: python api_version: 1 handlers: - url: .* script: doodleapps.py
We want the script to run automatically every 24 hours, without the need for the administrator to send a request, so we also have to define another configuration file called cron.yaml:
cron.yaml
cron: - description: daily doodle update url: / schedule: every 24 hours
Once the application is deployed on App Engine, it will run the script on a daily basis and update the logo.
The holiday season is upon us. Could there be a better time for your company to start using doodles?
Happy Holidays!
Managing the user accounts in a Google Apps domain can be a daunting task when you have hundreds or thousands of them and you have no tools to automate the process. The Google Apps Provisioning API allows developers to write user management applications in the programming language of their choice, but many system administrators prefer a script-based solution instead. The recently launched UserManager Apps Script service fills the gap, providing Google Apps domain administrators an easy way to automate tasks such as batch user creation or update.
With the new Apps Script service, creating a user will be as easy as writing a single line of code:
var user = UserManager.createUser("newuser", "John", "Smith", "mypassword");
The UserManager service also makes it easy to perform the same task on each account in the domain. The following sample shows how you can force all users to change their passwords at the next login:
var users = UserManager.getAllUsers(); for (var i in users) { users[i].setChangePasswordAtNextLogin(true); }
Calls to the UserManager service can also be scheduled to run hourly or daily, or in response to certain events thanks to Apps Script Triggers.
Interested in what else you can do with the UserManager service? Please check the documentation and get in touch with us on the the forum for any questions about its usage or to share more info about your project with the community.
Google Groups is a great way to foster communication over email and on the web, connecting people and allowing them to participate in and read archived discussions. Today, we are introducing the Google Groups Service in Google Apps Script. Groups Service will allow a script to check if a user belongs to a certain group, or to enumerate the members of a particular group. The Google Groups Service works with groups created through the Google Groups web interface as well as groups created by enterprise customers with their own domain using the control panel and the Google Apps Provisioning API.
This opens a wide range of possibilities, such as allowing a script with Ui Services to show additional buttons to the members of a particular group - for example teachers or managers - and sending customized emails to all the members of a group.
Here are a few sample scripts to help you get started with the new API. To try out these samples, select Create > New Spreadsheet and then Tools > Script Editor from the menu. You can then copy the code into the script editor. The scripts’ output will appear back in the spreadsheet.
The Groups Services can be used to fetch a list of the Google Groups of which you’re a member.
Below is a function which returns all the groups of which you’re a member. Copy and paste it into the script editor and run it. The editor will prompt you to grant READ access to the Google Groups Service before the script can run successfully.
If you receive a message stating that you’re not a member of any group, open up Google Groups and join any of the thousands of groups there.
function showMyGroups() { var groups = GroupsApp.getGroups(); var s; if (groups.length > 0) { s = "You belong to " + groups.length + " groups: "; for (var i = 0; i < groups.length; i++) { var group = groups[i]; if (i > 0) { s += ", "; } s += group.getEmail(); } } else { s = "You are not a member of any group!"; } Browser.msgBox(s); }
Brendan plays trumpet in a band. He also runs the band’s website and updates its Google+ page. He’s created a web application with Google Apps Script and now he wants to add to it some additional features for members of the band. Being a model Google user, he’s already subscribed each band member to a Google Group. Although building a complete UI with Google Apps Script is beyond the scope of this article, Brendan could adapt the following function to help make additional features available only to members of that Google Group.
Of course, this is not just useful for tech-savvy trumpet players: schools may wish to make certain features available just to teachers or others just to students; businesses may need to offer certain functionality to people managers or simply to show on a page or in a UI operations of interest to those in a particular department. Before running this example yourself, replace test@example.com with the email address of any group of which you’re a member.
test@example.com
Note: the group’s member list must be visible to the user running the script. Generally, this means you must yourself be a member of a group to successfully test if another user is a member of that same group. Additionally, group owners and managers can restrict member list access to group owners and managers. For such groups, you must be an owner or manager of the group to query membership.
function testGroupMembership() { var groupEmail = "test@example.com"; var group = GroupsApp.getGroupByName(groupEmail); if (group.hasUser(Session.getActiveUser().getEmail())) { Browser.msgBox("You are a member of " + groupEmail); } else { Browser.msgBox("You are not a member of " + groupEmail); } }
Sending an email to the group’s email address forwards that message to all the members of the group. Specifically, that message is forwarded to all those members who subscribe by email. Indeed, for many users, discussion over email is the principal feature of Google Groups.
Suppose, however, that you want to send a customised message to those same people. Provided you have permission to view a group’s member list, the Google Groups Service can be used to fetch the usernames of all the members of a group. The following script demonstrates how to fetch this list and then send an email to each member.
Before running this script, consider if you actually want to send a very silly message to all the members of the group. It may be advisable just to examine how the script works!
function sendCustomizedEmail() { var groupEmail = "test@example.com"; var group = GroupsApp.getGroupByEmail(groupEmail); var users = group.getUsers(); for (var i = 0; i < users.length; i++) { var user = users[i]; MailApp.sendEmail(user.getEmail(), "Thank you!", "Hello " + user.getEmail() + ", thank you for joining this group!"); } }
The Google Groups Service lets you query a user’s role within a group. One possible role is MANAGER (the other roles are described in detail in the Google Groups Service’s documentation): these users can perform administrative tasks on the group, such as renaming the group and accepting membership requests. Any user’s Role can be queried with the help of the Group class’ getRole() method.
This sample function may be used to fetch a list of a group’s managers. Once again, you must have access to the group’s member list for this function to run successfully:
function getGroupOwners(group) { var users = group.getUsers(); var managers = []; for (var i = 0; i < users.length; i++) { var user = users[i]; if (group.getRole(user) == GroupsApp.Role.MANAGER) { managers.push(user); } } return managers; }
Let us know what you end up building, or if you have any questions about this new functionality, by posting in the Apps Script forum.
Editor's note: this announcement is cross-posted from the Google Ads Developer Blog, which caters to AdWords, AdSense, DoubleClick and AdMob developers. We hope you enjoy this latest addition to Google Apps Script — Ryan Boyd
Starting today, the AdSense Management API is available as part of AdSense Services in Google Apps Script. This means that you’ll be able to do things like:
Accessing the API from Google Apps Scripts is very easy. The following snippet of code shows how to generate a report and populate columns of a spreadsheet with the data retrieved:
function generateReport() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName('Reports'); var startDate = Browser.inputBox( "Enter a start date (format: 'yyyy-mm-dd')"); var endDate = Browser.inputBox( "Enter an end date (format: 'yyyy-mm-dd')"); var args = { 'metric': ['PAGE_VIEWS', 'AD_REQUESTS', 'MATCHED_AD_REQUESTS', 'INDIVIDUAL_AD_IMPRESSIONS'], 'dimension': ['MONTH']}; var report = AdSense.Reports.generate(startDate, endDate, args).getRows(); for (var i=0; i<report.length; i++) { var row = report[i]; sheet.getRange('A' + String(i+2)).setValue(row[0]); sheet.getRange('B' + String(i+2)).setValue(row[1]); sheet.getRange('C' + String(i+2)).setValue(row[2]); sheet.getRange('D' + String(i+2)).setValue(row[3]); sheet.getRange('E' + String(i+2)).setValue(row[4]); } }
function generateLineChart() { var doc = SpreadsheetApp.getActiveSpreadsheet(); var startDate = Browser.inputBox( "Enter a start date (format: 'yyyy-mm-dd')"); var endDate = Browser.inputBox( "Enter an end date (format: 'yyyy-mm-dd')"); var adClientId = Browser.inputBox("Enter an ad client id"); var args = { 'filter': ['AD_CLIENT_ID==' + adClientId], 'metric': ['PAGE_VIEWS', 'AD_REQUESTS', 'MATCHED_AD_REQUESTS', 'INDIVIDUAL_AD_IMPRESSIONS'], 'dimension': ['MONTH']}; var report = AdSense.Reports.generate(startDate, endDate, args).getRows(); var data = Charts.newDataTable() .addColumn(Charts.ColumnType.STRING, "Month") .addColumn(Charts.ColumnType.NUMBER, "Page views") .addColumn(Charts.ColumnType.NUMBER, "Ad requests") .addColumn(Charts.ColumnType.NUMBER, "Matched ad requests") .addColumn(Charts.ColumnType.NUMBER, "Individual ad impressions"); // Convert the metrics to numeric values. for (var i=0; i<report.length; i++) { var row = report[i]; data.addRow([row[0],parseInt(row[1]),parseInt(row[2]), parseInt(row[3]),parseInt(row[4])]); } data.build(); var chart = Charts.newLineChart() .setDataTable(data) .setTitle("Performances per Month") .build(); var app = UiApp.createApplication().setTitle("Performances"); var panel = app.createVerticalPanel() .setHeight('350') .setWidth('700'); panel.add(chart); app.add(panel); doc.show(app); }