Warning: Table './devblogsdb/cache_page' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire, serialized FROM cache_page WHERE cid = 'http://www.softdevblogs.com/?q=aggregator/categories/1' in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 729

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 730

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 731

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 732
Software Development Blogs: Programming, Software Testing, Agile, Project Management
Skip to content

Software Development Blogs: Programming, Software Testing, Agile Project Management

Methods & Tools

Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

Programming
warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/common.inc on line 153.

Indie game developers in Latin America sustain growth after launch on Google Play

Android Developers Blog - Fri, 12/02/2016 - 16:06

Posted by Kacey Fahey, Marketing Programs Manager, Google Play

Indie game developers are some of the most exciting and innovative teams to work with. While developers large and small exist on the same field, gone are the days where you hit publish and turn your back, moving on to the next project. We've gathered a few developer stories coming out of Latin America sharing experiences and advice.

Oktagon Games

Ronaldo Cruz, Founder and CEO of Oktagon Games tells us how "reviews provide great qualitative insight on the game helping us identify problems that may not be caught by analytics."
Tiny Bytes

Tiny Bytes reduced churn by 5% using an in-game tutorial and analytics.

Impossible Apps

Cleverson Schmidt of Impossible Apps shares how introducing in-app purchases helps diversify revenue streams and "can make the game profitable and self sustainable."


How useful did you find this blogpost?
β˜† β˜† β˜† β˜† β˜†
Categories: Programming

Cypress - Dealing with flaky tests

Xebia Blog - Fri, 12/02/2016 - 10:32
Test automation is all about feedback. Feedback that gives you quality updates about the features your team has built. A continuous green build is always the goal because this should give you the confidence you need to go to production. Unfortunately, I’m more used to a β€œtraffic light build”, a build which passes and fails

Indie game developers in Latin America sustain growth after launch on Google Play

Android Developers Blog - Thu, 12/01/2016 - 21:24

Posted by Kacey Fahey, Marketing Programs Manager, Google Play

Indie game developers are some of the most exciting and innovative teams to work with. While developers large and small exist on the same field, gone are the days where you hit publish and turn your back, moving on to the next project. We've gathered a few developer stories coming out of Latin America sharing experiences and advice.

Oktagon Games

Ronaldo Cruz, Founder and CEO of Oktagon Games tells us how "reviews provide great qualitative insight on the game helping us identify problems that may not be caught by analytics."
Tiny Bytes

Tiny Bytes reduced churn by 5% using an in-game tutorial and analytics.

Impossible Apps

Cleverson Schmidt of Impossible Apps shares how introducing in-app purchases helps diversify revenue streams and "can make the game profitable and self sustainable."


How useful did you find this blogpost?
β˜† β˜† β˜† β˜† β˜†
Categories: Programming

Updated Udacity Android course prepares students for the Associate Android Developer Certification

Google Code Blog - Wed, 11/30/2016 - 20:41
Originally posted on Android Developers Blog

Posted by Jocelyn Becker, Senior Program Manager, Android Training

As one of our most popular Udacity courses, the Developing Android Appscourse was recently updated to ensure developers have the resources to build high quality apps. This course, which has already helped more than half a million developers learn to build Android apps, has been through the car wash and come out sparkling clean and updated.

Google and Udacity have worked together to update the course to include the very latest changes in Android and Android Studio, including how to use the new Constraint Layout editor, and how to use Firebase Job Dispatcher. Learn best practices for building Android apps using Android 7.0 (Nougat) while keeping your apps backwards compatible in older versions, learning at your own pace in your own time.

You sent us feedback that some of the lessons were a little difficult to get through, so we've restructured the lessons and added smaller apps for you to build as you progress through the course. So not only will you build the Sunshine weather app as a complete, integrated application that spans the entire course, but you'll also create an app in each lesson to help you learn individual concepts.

Build a To Do app and add new tasks as you learn how to build a ContentProvider.

This course brings back Android experts Dan Galpin and Reto Meier from Google, and Lyla Fujiwara from Udacity, and introduces new faces from Google and Udacity.
Start learning now at https://www.udacity.com/course/ud851.

Combined package for Developing Android Apps course and Associate Android Developer Certification

This updated course teaches the skills that are tested by the Associate Android Developer certification exam. Udacity is offering a package that combines the updated Developing Android Apps course with a voucher for the Associate Android Developer certification exam. If you pass this exam, you will earn the Associate Android Developer Certification and show that you are competent and skilled in tasks that an entry-level Android developer typically performs. Enroll in Udacity's Fast Track to get prepared and take the Associate Android developer exam at: https://www.udacity.com/course/nd818.

Categories: Programming

Generating slides from spreadsheet data

Google Code Blog - Wed, 11/30/2016 - 19:33
Originally posted on G Suite Developers Blog

Posted by Wesley Chun (@wescpy), Developer Advocate, G Suite

The G Suite team recently launched the very first Google Slides API, opening up a whole new set of possibilities, including leveraging data already sitting in a spreadsheet or database, and programmatically generating slide decks or slide content based on that data. Why is this a big deal? One of the key advantages of slide decks is that they can take database or spreadsheet data and make it more presentable for human consumption. This is useful when the need arises to communicate the information reflected by that data to management or potential customers.

Walking developers through a short application demonstrating both the Sheets and Slides APIs to make this happen is the topic of today's DevByte video. The sample app starts by reading all the necessary data from the spreadsheet using the Sheets API. The Slides API takes over from there, creating new slides for the data, then populating those slides with the Sheets data.

Developers interact with Slides by sending API requests. Similar to the Google Sheets API, these requests come in the form of JSON payloads. You create an array like in the JavaScript pseudocode below featuring requests to create a cell table on a slide and import a chart from a Sheet:


var requests = [    {"createTable": {        "elementProperties":            {"pageObjectId": slideID},        "rows": 8,        "columns": 4    }},    {"createSheetsChart": {        "spreadsheetId": sheetID,        "chartId": chartID,        "linkingMode": "LINKED",        "elementProperties": {            "pageObjectId": slideID,            "size": {                "height": { ... },                "width": { ... }            },            "transform": { ... }        }    }}];
If you've got at least one request, say in a variable named requests (as above), including the Sheet's sheetID and chartID plus the presentation page's slideID. You'd then pass it to the API with just one call to the presentations().batchUpdate() command, which in Python looks like the below if SLIDES is your API service endpoint:
SLIDES.presentations().batchUpdate(presentationId=slideID,        body=requests).execute()

Creating tables is fairly straightforward. Creating charts has some magical features, one of those being the linkingMode. A value of "LINKED" means that if the Sheet data changes (altering the chart in the Sheet), the same chart in a slide presentation can be refreshed to match the latest image, either by the API or in the Slides user interface! You can also request a plain old static image that doesn't change with the data by selecting a value of "NOT_LINKED_IMAGE" for linkingMode. More on this can be found in the documentationon creating charts, and check out the video where you'll see both those API requests in action.

For a detailed look at the complete code sample featured in the video, check out the deep dive post. We look forward to seeing the interesting integrations you build with the power of both APIs!

Categories: Programming

Generating slides from spreadsheet data

Google Code Blog - Wed, 11/30/2016 - 19:33
Originally posted on G Suite Developers Blog

Posted by Wesley Chun (@wescpy), Developer Advocate, G Suite

The G Suite team recently launched the very first Google Slides API, opening up a whole new set of possibilities, including leveraging data already sitting in a spreadsheet or database, and programmatically generating slide decks or slide content based on that data. Why is this a big deal? One of the key advantages of slide decks is that they can take database or spreadsheet data and make it more presentable for human consumption. This is useful when the need arises to communicate the information reflected by that data to management or potential customers.

Walking developers through a short application demonstrating both the Sheets and Slides APIs to make this happen is the topic of today's DevByte video. The sample app starts by reading all the necessary data from the spreadsheet using the Sheets API. The Slides API takes over from there, creating new slides for the data, then populating those slides with the Sheets data.

Developers interact with Slides by sending API requests. Similar to the Google Sheets API, these requests come in the form of JSON payloads. You create an array like in the JavaScript pseudocode below featuring requests to create a cell table on a slide and import a chart from a Sheet:


var requests = [    {"createTable": {        "elementProperties":            {"pageObjectId": slideID},        "rows": 8,        "columns": 4    }},    {"createSheetsChart": {        "spreadsheetId": sheetID,        "chartId": chartID,        "linkingMode": "LINKED",        "elementProperties": {            "pageObjectId": slideID,            "size": {                "height": { ... },                "width": { ... }            },            "transform": { ... }        }    }}];
If you've got at least one request, say in a variable named requests (as above), including the Sheet's sheetID and chartID plus the presentation page's slideID. You'd then pass it to the API with just one call to the presentations().batchUpdate() command, which in Python looks like the below if SLIDES is your API service endpoint:
SLIDES.presentations().batchUpdate(presentationId=slideID,        body=requests).execute()

Creating tables is fairly straightforward. Creating charts has some magical features, one of those being the linkingMode. A value of "LINKED" means that if the Sheet data changes (altering the chart in the Sheet), the same chart in a slide presentation can be refreshed to match the latest image, either by the API or in the Slides user interface! You can also request a plain old static image that doesn't change with the data by selecting a value of "NOT_LINKED_IMAGE" for linkingMode. More on this can be found in the documentationon creating charts, and check out the video where you'll see both those API requests in action.

For a detailed look at the complete code sample featured in the video, check out the deep dive post. We look forward to seeing the interesting integrations you build with the power of both APIs!

Categories: Programming

Updated Udacity Android course prepares students for the Associate Android Developer Certification

Android Developers Blog - Wed, 11/30/2016 - 18:45

Posted by Jocelyn Becker, Senior Program Manager, Android Training

As one of our most popular Udacity courses, the Developing Android Apps course was recently updated to ensure developers have the resources to build high quality apps. This course, which has already helped more than half a million developers learn to build Android apps, has been through the car wash and come out sparkling clean and updated.

Google and Udacity have worked together to update the course to include the very latest changes in Android and Android Studio, including how to use the new Constraint Layout editor, and how to use Firebase Job Dispatcher. Learn best practices for building Android apps using Android 7.0 (Nougat) while keeping your apps backwards compatible in older versions, learning at your own pace in your own time.

You sent us feedback that some of the lessons were a little difficult to get through, so we've restructured the lessons and added smaller apps for you to build as you progress through the course. So not only will you build the Sunshine weather app as a complete, integrated application that spans the entire course, but you'll also create an app in each lesson to help you learn individual concepts.

Build a To Do app and add new tasks as you learn how to build a ContentProvider.

This course brings back Android experts Dan Galpin and Reto Meier from Google, and Lyla Fujiwara from Udacity, and introduces new faces from Google and Udacity.
Start learning now at https://www.udacity.com/course/ud851.

Combined package for Developing Android Apps course and Associate Android Developer Certification

This updated course teaches the skills that are tested by the Associate Android Developer certification exam. Udacity is offering a package that combines the updated Developing Android Apps course with a voucher for the Associate Android Developer certification exam. If you pass this exam, you will earn the Associate Android Developer Certification and show that you are competent and skilled in tasks that an entry-level Android developer typically performs. Enroll in Udacity's Fast Track to get prepared and take the Associate Android developer exam at: https://www.udacity.com/course/nd818.

Categories: Programming

Learn tips from Memrise to increase in-app conversions with pricing experiments

Android Developers Blog - Wed, 11/30/2016 - 16:41

Posted by Tamzin Taylor, Partner Development Manager at Google Play, & Kristina Narusk, Head of Production at Memrise

Getting people to install your app is one thing, getting them to sign up to your paid offering is quite another. It's important to understand the complete journey your users take from installing your app to paying for something. Once you do, you can experiment on the flow to try and increase conversions. Memrise has found great success in experimenting on their language learning app to increase the number of paying users.

Four experiments Memrise use to improve conversions

Memrise makes languages fun with a number of different learning modes you can play to help increase your vocabulary in a chosen language. You can download the app for free and play some of the modes or take advantage of their premium subscription offering called 'Memrise Pro' which offers new game modes and additional features like offline learning. Memrise recently ran a number of conversion experiments with the main objective of increasing the Average Revenue Per Daily Active User (ARPDAU). These experiments tested multiple user experience and pricing experiment scenarios.

1. A/B test how messaging different user benefits can impact conversion

What they did: Memrise wanted to know what motivation and call to action would convert the most users to buy a Pro subscription from a locked game mode in the app. To do this, they ran an A/B test with two similar designs, featuring different reasons for the user to upgrade, and compared the results to their original upgrade messaging.



Screen Shot 2016-10-11 at 15.26.00.png Screen Shot 2016-10-11 at 15.25.34.png Test A: Focus on β€˜difficult’ words with an orange background. Test B: Focus on β€˜favorite’ words with a pink background.

Results: Test A performed the best. Conversion to Pro in Test A was 28% higher than in Test B. Pro mode usage was subsequently 9.7% higher in Test A compared to Test B too.

Next steps: After seeing how test A won the experiment, Memrise applied this creative across the board. Subscribers driven by that particular mode increased as a percentage of all subscriptions in the app by 16%. Memrise plans to run additional A/B tests at others points of conversion in the app to see if they can increase the results even further. They'll also try different text for the call to actions.

2. Test whether adapting to local price points results in sustainable uplift

In 2015, Google Play launched new minimum local price levels in countries around the world. To take advantage of the new price points, Memrise tested lowering localised prices in certain markets to better match purchasing power. Prices were an average of 6 times lower during this experiment.

Results: After 30 days, Memrise saw the following changes in conversions to paid users:



Categories: Programming

Calling European game developers, enter the Indie Games Contest by December 31

Android Developers Blog - Wed, 11/30/2016 - 03:32
Originally posted on Google Developers blog

Posted by Matteo Vallone, Google Play Games Business Development

To build awareness of the awesome innovation and art that indie game developers are bringing to users on Google Play, we have invested heavily over the past year in programs like Indie Corner, as well as events like the Google Play Indie Games Festivals in North America and Korea.

As part of that sustained effort, we also want to celebrate the passion and innovation of indie game developers with the introduction of the first-ever Google Play Indie Games Contest in Europe. The contest will recognize the best indie talent in several countries and offer prizes that will help you get your game noticed by industry experts and gamers worldwide.

Prizes for the finalists and winners:

  • An open showcase held at the Saatchi Gallery in London
  • YouTube influencer campaigns worth up to 100,000 EUR
  • Premium placements on Google Play
  • Tickets to Google I/O 2017 and other top industry events
  • Promotions on our channels
  • Special prizes for the best Unity game
  • And more!

Entering the contest:

If you're based in Czech Republic, Denmark, Finland, France (coming soon), Germany, Iceland, Israel, Netherlands, Norway, Poland (coming soon), Romania, Spain, Sweden, Turkey, or UK (excl. Northern Ireland), have 15 or less full time employees, and published a new game on Google Play after 1 January 2016, you may now be eligible to enter the contest. If you're planning on publishing a new game soon, you can also enter by submitting a private beta. Check out all the details in the terms and conditions. Submissions close on 31 December 2016.

The process:

Up to 20 finalists will get to showcase their games at an open event at the Saatchi Gallery in London on the 16th February 2017. At the event, the top 10 will be selected by the event attendees and the Google Play team. The top 10 will then get the opportunity to pitch to a jury of industry experts, from which the final winner and runners up will be selected.

Even if someone is NOT entering the contest:

Even if you're not eligible to enter the contest, you can still register to attend the final showcase event in London on 16 February 2017, check out some great indie games, and have fun with various industry experts and indie developers. We will also be hosting a workshop for all indie games developers from across EMEA in the new Google office in Kings Cross the next day, so this will be a packed week.

Get started:

Enter the Indie Games Contest now and visit the contest site to find out more about the contest, the event, and the workshop.

Categories: Programming

Your next growth market: Realizing the potential of MENA

Android Developers Blog - Tue, 11/29/2016 - 23:58

Posted by Mohammad El-Saadi, BD, Google Play

We know that many developers want to take advantage of growth opportunities in new regions, but are held back by not knowing the most important areas to focus on. That's why we wanted to share stories from our partners in the Middle East and North Africa (MENA). It's a fast growing region for Google Play, and one that already represents a sizable revenue opportunity. They've shared their experiences, and some key things to focus on if you're thinking of launching in the region.

Middle East and North Africa overview

MENA is a diverse region in terms of disposable income, access to connectivity, and smartphone penetration. However, it is possible to broadly group MENA into two types of market:

Growth markets

  • Examples: Saudi Arabia, United Arab Emirates (UAE), Kuwait and the rest of the Gulf Cooperation Council (GCC).
  • Very high smartphone penetration (on par with top western european markets),
  • Large disposable income
  • Robust growth in spend on mobile apps and games

Emerging markets

  • Examples: Morocco, Egypt and Iraq.
  • Large populations
  • Significant growth in smartphone (primarily Android) adoption.

Opportunities

Localization

If you want to be successful in MENA, localization is key. In Saudi Arabia 19 of the top 20 grossing apps & games have their Google Play Store listing localized and the majority of those have their actual app/game localized as well. By localizing to Arabic, mobile app and game developers have found great success in the region.

When Singapore-based Wego.com localized to Arabic, they achieved over 200% YoY growth in MENA, grew their app rating from 3.5 to over 4.5 among Arab travelers and increased Arab users' retention rates by 200%. Today, MENA represents over 65% of their users.

To do localization well, here are a few things to consider:

  • Localize your store listing into Arabic including your video, screenshots and text. If you are targeting specific countries within MENA consider using local dialects, otherwise use formal Arabic. Consider using Store Listing Experiments to optimize your listing for local audiences.
  • If applicable, flip your app/game UI to be right-to-left.
  • Beware of common issues when localizing to Arabic: Arabic letters appearing disjointed or showing up in reverse order and the ordering of words getting mixed up when sentences contain both Latin and Arabic words
  • Localize pricing by showing appropriate local currency and rounding. Note that different countries in MENA have different currencies and affordability/willingness to pay.
  • Plan around major local events such as the holy month of Ramadan, when after fasting from dawn to sunset, families and loved ones gather for meals, laughs and stories. We've found that during this month usage of apps and games increases significantly in MENA.
  • Provide local customer support
  • Be culturally sensitive in your communication and content - avoid stereotypes and keep in mind the relatively conservative nature of users in the region
  • Leverage the power of YouTube to reach your audiences in MENA. Saudi Arabia for instance is the second largest market for YouTube globally in terms of views per capita.

Refer to our Localization Checklist for some best practices when localizing for any language.

Gaming

Gaming is a high growth and revenue opportunity in MENA. Most countries in the region have a median age of 30 or lower, smartphone growth will continue to grow at double digits, which makes gaming a key segment for users in the region. Today's local top grossing charts and dominated by Midcore strategy games. Interestingly, GCC countries have some of the highest Average Revenue Per Paying User rates globally.

International titles, including Clash of Clans, Clash Royale, Mobile Strike and Clash of Kings, have performed incredibly well in the region. In addition, titles specifically targeting MENA have also seen tremendous success. Revenge of the Sultans, by ONEMT, from China, has been the top grossing title across several MENA countries for many months. Similarly, when IGG.com launched the Arabic version of Castle Clash, they grew revenue from MENA by 58% within 4 months.

As the market evolves, there is also a huge opportunity for other genres (such as RPG, FPS, and sports) which are not present at scale in the region yet.

Google Play in MENA

We continue to invest in making sure that users are able to pay for their favorite apps and games by launching locally relevant payment methods in MENA. Today, we have carrier billing available with the major networks in Saudi Arabia, UAE and Kuwait. We plan to expand coverage in more countries, including Qatar and Bahrain, in the future.

We are also committed to increasing the quality and availability of Arabic apps and games for MENA users, which is why we launched our Now in Arabic collection featuring apps and games that have recently localized to Arabic. This collection will be regularly updated. If you're interested in being included, submit your localized app/game.

Categories: Programming

Android Developer Story: Le Monde increases subscriptions with Google Play Billing

Android Developers Blog - Tue, 11/29/2016 - 19:07

Watch Edouard Andrieu, Director of Mobile, and Ahcene Amrouz, Product Manager for Mobile, explain how La Matinale has a 6% higher subscription conversion on Android than on other platforms thanks to tools like Google Play Billing.

Learn more how to add an introductory price to your subscription, and get the News Publisher Playbook to stay up-to-date with more features and best practices to help you find success for your news apps on Google Play.


How useful did you find this blogpost?
β˜† β˜† β˜† β˜† β˜†
Categories: Programming

Keeping it real: Improving reviews and ratings in Google Play

Android Developers Blog - Tue, 11/29/2016 - 18:49

Posted by Andrew Ahn, Product Manager and Buddhika Kottahachchi, Product Manager

The Play Store contains the largest catalog of apps in the world. As our users make decisions about the apps they'd like to install, we want to ensure Play provides a trustworthy experience.

Recently, we announced our improvements in fighting fraudulent and spam app installs. In continuing our efforts to combat spammy behavior, we've also improved the ways we identify and remove fake reviews and ratings. With this enhanced capability we are now able to identify and remove more fake reviews and ratings with greater accuracy.

In the vast majority of cases, no action is needed. If you are working with someone else to promote your app (e.g., third-party marketing agencies), we advise you to check-in and ensure that their promotion techniques use legitimate practices, and adhere to the Google Play Developer Policy. The basic rule of thumb for reviews and ratings is that they should come from genuine users, and developers should not attempt to manipulate them in any form (e.g., fake, paid, incentivized).

We will continue making such enhancements to our systems that will further help protect the integrity of Google Play, our developer community, and ultimately our end users.

Categories: Programming

TensorFlow 0.12 adds support for Windows

Google Code Blog - Tue, 11/29/2016 - 18:32
Posted by Derek Murray, Software Engineer
Today we are launching preliminary Windows support for TensorFlow.

Native support for TensorFlow on Windows was one of the first requests we received after open-sourcing TensorFlow. Although some Windows users have managed to run TensorFlow in a Docker container, we wanted to provide a more complete experience including GPU support.

With the release of TensorFlow r0.12, we now provide a native TensorFlow package for Windows 7, 10, and Server 2016. This release enables you to speed up your TensorFlow training with any GPU that runs CUDA 8.

We have published the latest release as a pip package in PyPI, so now you can install TensorFlow with a single command:

     C:\> pip install tensorflow

And for GPU support:

     C:\> pip install tensorflow-gpu

More details about Windows support and all of the other new features in r0.12 are included in the release notes.

We're excited to offer more people the opportunity to use TF at maximum speed. Follow us on Twitter to be the first to hear about future releases – we're @tensorflow.

Acknowledgements

Many people have contributed to making this release possible. In particular, we'd like to thank Guenther Schmuelling and Vit Stepanovs from Microsoft for their significant contributions to Windows support.

Categories: Programming

It’s that time again: Google Code-in starts today!

Google Code Blog - Mon, 11/28/2016 - 21:33
Originally posted on Google Open Source Blog
By Mary Radomile, Open Source Programs Office
Today marks the start of the 7th year of Google Code-in (GCI), our pre-university contest introducing students to open source development. GCI takes place entirely online and is open to students between the ages of 13 and 17 around the globe.
The concept is simple: complete bite-sized tasks (at your own pace) created by 17 participating open source organizations on topic areas you find interesting:

  • Coding
  • Documentation/Training
  • Outreach/Research
  • Quality Assurance
  • User Interface

Tasks take an average of 3-5 hours to complete and include the guidance of a mentor to help along the way. Complete one task? Get a digital certificate. Three tasks? Get a sweet Google t-shirt. Finalists get a hoodie. Grand Prize winners get a trip to Google headquarters in California.

Over the last 6 years, 3213 students from 99 countries have successfully completed tasks in GCI. Intrigued? Learn more about GCI by checking out our rules and FAQs. And please visit our contest site and read the Getting Started Guide.

Teachers, if you are interested in getting your students involved in Google Code-in you can find resources here to help you get started.

Categories: Programming

Kubernetes: Spinning up a Neo4j 3.1 Causal Cluster

Mark Needham - Fri, 11/25/2016 - 17:55

A couple of weeks ago I wrote a blog post explaining how I’d created a Neo4j causal cluster using docker containers directly and for my next pet project I wanted to use Kubernetes as an orchestration layer so that I could declaratively change the number of servers in my cluster.

I’d never used Kubernetes before but I saw a presentation showing how to use it to create an Elastic cluster at the GDG Cloud meetup a couple of months ago.

In that presentation I was introduced to the idea of a PetSet which is an abstraction exposed by Kubernetes which allows us to manage a set of pods (containers) which have a fixed identity. The documentation explains it better:

A PetSet ensures that a specified number of β€œpets” with unique identities are running at any given time. The identity of a Pet is comprised of:

  • a stable hostname, available in DNS
  • an ordinal index
  • stable storage: linked to the ordinal & hostname

In my case I need to have a stable hostname because each member of a Neo4j cluster is given a list of other cluster members with which it can create a new cluster or join an already existing one. This is the first use case described in the documentation:

PetSet also helps with the 2 most common problems encountered managing such clustered applications:

  • discovery of peers for quorum
  • startup/teardown ordering

So the first thing we need to do is create some stable storage for our pods to use.

We’ll create a cluster of 3 members so we need to create one PersistentVolume for each of them. The following script does the job:

volumes.sh

for i in $(seq 0 2); do
  cat <<EOF | kubectl create -f -
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv${i}
  labels:
    type: local
    app: neo4j
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/tmp/${i}"
EOF
 
  cat <<EOF | kubectl create -f -
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: datadir-neo4j-${i}
  labels:
    app: neo4j
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
done;

If we run this script it’ll create 3 volumes which we can see by running the following command:

$ kubectl get pv
NAME      CAPACITY   ACCESSMODES   STATUS    CLAIM                     REASON    AGE
pv0       1Gi        RWO           Bound     default/datadir-neo4j-0             7s
pv1       1Gi        RWO           Bound     default/datadir-neo4j-1             7s
pv2       1Gi        RWO           Bound     default/datadir-neo4j-2             7s
$ kubectl get pvc
NAME              STATUS    VOLUME    CAPACITY   ACCESSMODES   AGE
datadir-neo4j-0   Bound     pv0       1Gi        RWO           26s
datadir-neo4j-1   Bound     pv1       1Gi        RWO           26s
datadir-neo4j-2   Bound     pv2       1Gi        RWO           25s

Next we need to create a PetSet template. After a lot of iterations I ended up with the following:

# Headless service to provide DNS lookup
apiVersion: v1
kind: Service
metadata:
  labels:
    app: neo4j
  name: neo4j
spec:
  clusterIP: None
  ports:
    - port: 7474
  selector:
    app: neo4j
----
# new API name
apiVersion: "apps/v1alpha1"
kind: PetSet
metadata:
  name: neo4j
spec:
  serviceName: neo4j
  replicas: 3
  template:
    metadata:
      annotations:
        pod.alpha.kubernetes.io/initialized: "true"
        pod.beta.kubernetes.io/init-containers: '[
            {
                "name": "install",
                "image": "gcr.io/google_containers/busybox:1.24",
                "command": ["/bin/sh", "-c", "echo \"
                unsupported.dbms.edition=enterprise\n
                dbms.mode=CORE\n
                dbms.connectors.default_advertised_address=$HOSTNAME.neo4j.default.svc.cluster.local\n
                dbms.connectors.default_listen_address=0.0.0.0\n
                dbms.connector.bolt.type=BOLT\n
                dbms.connector.bolt.enabled=true\n
                dbms.connector.bolt.listen_address=0.0.0.0:7687\n
                dbms.connector.http.type=HTTP\n
                dbms.connector.http.enabled=true\n
                dbms.connector.http.listen_address=0.0.0.0:7474\n
                causal_clustering.raft_messages_log_enable=true\n
                causal_clustering.initial_discovery_members=neo4j-0.neo4j.default.svc.cluster.local:5000,neo4j-1.neo4j.default.svc.cluster.local:5000,neo4j-2.neo4j.default.svc.cluster.local:5000\n
                causal_clustering.leader_election_timeout=2s\n
                  \" > /work-dir/neo4j.conf" ],
                "volumeMounts": [
                    {
                        "name": "confdir",
                        "mountPath": "/work-dir"
                    }
                ]
            }
        ]'
      labels:
        app: neo4j
    spec:
      containers:
      - name: neo4j
        image: "neo4j/neo4j-experimental:3.1.0-M13-beta3-enterprise"
        imagePullPolicy: Always
        ports:
        - containerPort: 5000
          name: discovery
        - containerPort: 6000
          name: tx
        - containerPort: 7000
          name: raft
        - containerPort: 7474
          name: browser
        - containerPort: 7687
          name: bolt
        securityContext:
          privileged: true
        volumeMounts:
        - name: datadir
          mountPath: /data
        - name: confdir
          mountPath: /conf
      volumes:
      - name: confdir
  volumeClaimTemplates:
  - metadata:
      name: datadir
      annotations:
        volume.alpha.kubernetes.io/storage-class: anything
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

The main thing I had trouble with was getting the members of the cluster to talk to each other. The default docker config uses hostnames but I found that pods were unable to contact each other unless I specified the FQDN in the config file. We can run the following command to create the PetSet:

$ kubectl create -f neo4j.yaml 
service "neo4j" created
petset "neo4j" created

We can check if the pods are up and running by executing the following command:

$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
neo4j-0   1/1       Running   0          2m
neo4j-1   1/1       Running   0          14s
neo4j-2   1/1       Running   0          10s

And we can tail neo4j’s log files like this:

$ kubectl logs neo4j-0
Starting Neo4j.
2016-11-25 16:39:50.333+0000 INFO  Starting...
2016-11-25 16:39:51.723+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2016-11-25 16:39:51.733+0000 INFO  Initiating metrics...
2016-11-25 16:39:51.911+0000 INFO  Waiting for other members to join cluster before continuing...
2016-11-25 16:40:12.074+0000 INFO  Started.
2016-11-25 16:40:12.428+0000 INFO  Mounted REST API at: /db/manage
2016-11-25 16:40:13.350+0000 INFO  Remote interface available at http://neo4j-0.neo4j.default.svc.cluster.local:7474/
$ kubectl logs neo4j-1
Starting Neo4j.
2016-11-25 16:39:53.846+0000 INFO  Starting...
2016-11-25 16:39:56.212+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2016-11-25 16:39:56.225+0000 INFO  Initiating metrics...
2016-11-25 16:39:56.341+0000 INFO  Waiting for other members to join cluster before continuing...
2016-11-25 16:40:16.623+0000 INFO  Started.
2016-11-25 16:40:16.951+0000 INFO  Mounted REST API at: /db/manage
2016-11-25 16:40:17.607+0000 INFO  Remote interface available at http://neo4j-1.neo4j.default.svc.cluster.local:7474/
$ kubectl logs neo4j-2
Starting Neo4j.
2016-11-25 16:39:57.828+0000 INFO  Starting...
2016-11-25 16:39:59.166+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2016-11-25 16:39:59.176+0000 INFO  Initiating metrics...
2016-11-25 16:39:59.329+0000 INFO  Waiting for other members to join cluster before continuing...
2016-11-25 16:40:19.216+0000 INFO  Started.
2016-11-25 16:40:19.675+0000 INFO  Mounted REST API at: /db/manage
2016-11-25 16:40:21.029+0000 INFO  Remote interface available at http://neo4j-2.neo4j.default.svc.cluster.local:7474/

I wanted to log into the servers from my host machine’s browser so I setup port forwarding for each of the servers:

$ kubectl port-forward neo4j-0 7474:7474 7687:7687

We can then get an overview of the cluster by running the following procedure:

CALL dbms.cluster.overview()
 
╒════════════════════════════════════╀═════════════════════════════════════════════════════╀════════╕
β”‚id                                  β”‚addresses                                            β”‚role    β”‚
β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•ͺ═════════════════════════════════════════════════════β•ͺ════════║
β”‚81d8e5e2-02db-4414-85de-a7025b346e84β”‚[bolt://neo4j-0.neo4j.default.svc.cluster.local:7687,β”‚LEADER  β”‚
β”‚                                    β”‚ http://neo4j-0.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚347b7517-7ca0-4b92-b9f0-9249d46b2ad3β”‚[bolt://neo4j-1.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-1.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚a5ec1335-91ce-4358-910b-8af9086c2969β”‚[bolt://neo4j-2.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-2.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

So far so good. What if we want to have 5 servers in the cluster instead of 3? We can run the following command to increase our replica size:

$ kubectl patch petset neo4j -p '{"spec":{"replicas":5}}'
"neo4j" patched

Let’s run that procedure again:

CALL dbms.cluster.overview()
 
╒════════════════════════════════════╀═════════════════════════════════════════════════════╀════════╕
β”‚id                                  β”‚addresses                                            β”‚role    β”‚
β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•ͺ═════════════════════════════════════════════════════β•ͺ════════║
β”‚81d8e5e2-02db-4414-85de-a7025b346e84β”‚[bolt://neo4j-0.neo4j.default.svc.cluster.local:7687,β”‚LEADER  β”‚
β”‚                                    β”‚ http://neo4j-0.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚347b7517-7ca0-4b92-b9f0-9249d46b2ad3β”‚[bolt://neo4j-1.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-1.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚a5ec1335-91ce-4358-910b-8af9086c2969β”‚[bolt://neo4j-2.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-2.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚28613d06-d4c5-461c-b277-ddb3f05e5647β”‚[bolt://neo4j-3.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-3.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚2eaa0058-a4f3-4f07-9f22-d310562ad1ecβ”‚[bolt://neo4j-4.neo4j.default.svc.cluster.local:7687,β”‚FOLLOWERβ”‚
β”‚                                    β”‚ http://neo4j-4.neo4j.default.svc.cluster.local:7474]β”‚        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Neat! And it’s as easy to go back down to 3 again:

$ kubectl patch petset neo4j -p '{"spec":{"replicas":3}}'
"neo4j" patched
CALL dbms.cluster.overview()
 
╒════════════════════════════════════╀══════════════════════════════════════════════════════╀════════╕
β”‚id                                  β”‚addresses                                             β”‚role    β”‚
β•žβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•ͺ══════════════════════════════════════════════════════β•ͺ════════║
β”‚81d8e5e2-02db-4414-85de-a7025b346e84β”‚[bolt://neo4j-0.neo4j.default.svc.cluster.local:7687, β”‚LEADER  β”‚
β”‚                                    β”‚http://neo4j-0.neo4j.default.svc.cluster.local:7474]  β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚347b7517-7ca0-4b92-b9f0-9249d46b2ad3β”‚[bolt://neo4j-1.neo4j.default.svc.cluster.local:7687, β”‚FOLLOWERβ”‚
β”‚                                    β”‚http://neo4j-1.neo4j.default.svc.cluster.local:7474]  β”‚        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚a5ec1335-91ce-4358-910b-8af9086c2969β”‚[bolt://neo4j-2.neo4j.default.svc.cluster.local:7687, β”‚FOLLOWERβ”‚
β”‚                                    β”‚http://neo4j-2.neo4j.default.svc.cluster.local:7474]  β”‚        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Next I need to look at how we can add read replicas into the cluster. These don’t take part in the membership/quorum algorithm so I think I’ll be able to use the more common ReplicationController/Pod architecture for those.

If you want to play around with this the code is available as a gist. I’m using the minikube library for all my experiments but I’ll hopefully get around to trying this on GCE or AWS soon.

Categories: Programming

Nomad 0.5 configuration templates: consul-template is dead! long live consul-template!

Xebia Blog - Thu, 11/24/2016 - 09:20
Or... has Nomad made the Consul-template tool obsolete? If you employ Consul or Vault to provide service discovery or secrets management to your applications you will love the freshly released 0.5 version of the Nomad workload scheduler: it includes a new 'template' feature to dynamically generate configuration files fromΒ Consul andΒ Vault data for the jobs it

Final update to Android 7.1 Developer Preview

Android Developers Blog - Thu, 11/24/2016 - 01:05

Posted by Dave Burke, VP of Engineering

Today we're rolling out an update to the Android 7.1 Developer Preview -- the last before we release the final Android 7.1.1 platform to the ecosystem. Android 7.1.1 includes the developer features already available on Pixel and Pixel XL devices and adds optimizations and bug fixes on top of the base Android 7.1 platform. With Developer Preview 2, you can make sure your apps are ready for Android 7.1.1 and the consumers that will soon be running it on their devices.

As highlighted in October, we're also expanding the range of devices that can receive this Developer Preview update to Nexus 5X, Nexus 6P, Nexus 9, and Pixel C.

If you have a supported device that's enrolled in the Android Beta Program, you'll receive an update to Developer Preview 2 over the coming week. If you haven't enrolled your device yet, just visit the site to enroll your device and get the update.

In early December, we'll roll out Android 7.1.1 to the full lineup of supported devices as well as Pixel and Pixel XL devices.

What's in this update?

Developer Preview 2 is a release candidate for Android 7.1.1 that you can use to complete your app development and testing in preparation for the upcoming final release. In includes near-final system behaviors and UI, along with the latest bug fixes and optimizations across the system and Google apps.

It also includes the developer features and APIs (API level 25) already introduced in Developer Preview 1. If you haven't explored the developer features, you'll want to take a look at app shortcuts, round icon resources, and image keyboard support, among others -- you can see the full list of developer features here.

With Developer Preview 2, we're also updating the SDK build and platform tools in Android Studio, the Android 7.1.1 platform, and the API Level 25 emulator system images. The latest version of the support library (25.0.1) is also available for you to add image keyboard support, bottom navigation, and other features for devices running API Level 25 or earlier.

For details on API Level 25 check out the API diffs and the updated API reference on the developer preview site.

Get your apps ready for Android 7.1

Now is the time to optimize your apps to look their best on Android 7.1.1. To get started, update to Android Studio 2.2.2 and then download the API Level 25 platform, emulator system images, and tools through the SDK Manager in Android Studio.

After installing the API Level 25 SDK, you can update your project's compileSdkVersion to 25 to build and test against the new APIs. If you're doing compatibility testing, we recommend updating your app's targetSdkVersion to 25 to test your app with compatibility behaviors disabled. For details on how to set up your app with the API Level 25 SDK, see Set up the Preview.

If you're adding app shortcuts or circular launcher icons to your app, you can use Android Studio's built-in Image Asset Studio to quickly help you create icons of different sizes that meet the material design guidelines. You can test your round icons on the Google APIs emulator for API Level 25, which includes support for round icons and the new Google Pixel Launcher.

table.GeneratedTable td, table.GeneratedTable th { border-collapse: collapse; border-width: 1px; border-color: #000000; border-style: solid; }

Android Studio and the Google APIs emulator let you quickly create and test your round icon assets.

If you're adding image keyboard support, you can use the Messenger and Google Keyboard apps included in the preview system images for testing as they include support for this new API.

Scale your tests using Firebase Test Lab for Android

To help scale your testing, make sure to take advantage of Firebase Test Lab for Android and run your tests in the cloud at no charge during the preview period on all virtual devices including the Developer Preview 2 (API 25). You can use the automated crawler (Robo Test) to test your app without having to write any test scripts, or you can upload your own instrumentation (e.g. Espresso) tests. You can upload your tests here.

Publish your apps to alpha, beta or production channels in Google Play

After you've finished final testing, you can publish your updates compiled against, and optionally targeting, API 25 to Google Play. You can publish to your alpha, beta, or even production channels in the Google Play Developer Console. In this way, push your app updates to users whose devices are running Android 7.1, such as Pixel and Android Beta devices.

Get Developer Preview 2 on Your Eligible Device

If you have an eligible device that's already enrolled in the Android Beta Program, the device will get the Developer Preview 2 update over the coming week. No action is needed on your part. If you aren't yet enrolled in program, the easiest way to get started is by visiting android.com/beta and opt-in your eligible Android phone or tablet -- you'll soon receive this preview update over-the-air. As always, you can also download and flash this update manually.

As mentioned above, this Developer Preview update is available for Nexus 5X, Nexus 6P, Nexus 9, and Pixel C devices.

We're expecting to launch the final release of the Android 7.1.1 in just a few weeks Starting in December, we'll roll out Android 7.1.1 to the full lineup of supported preview devices, as well as the recently launched Pixel and Pixel XL devices. At that time, we'll also push the sources to AOSP, so our device manufacturer partners can bring this new platform update to consumers on their devices.

Meanwhile, we continue to welcome your feedback in the Developer Preview issue tracker, N Preview Developer community, or Android Beta community as we work towards the final consumer release in December!

Categories: Programming

Let's Encrypt Everything

Coding Horror - Jeff Atwood - Wed, 11/23/2016 - 01:03

I'll admit I was late to the HTTPS party.

But post Snowden, and particularly after the result of the last election here in the US, it's clear that everything on the web should be encrypted by default.

Why?

  1. You have an unalienable right to privacy, both in the real world and online. And without HTTPS you have zero online privacy – from anyone else on your WiFi, from your network provider, from website operators, from large companies, from the government.

  2. The performance penalty of HTTPS is gone, in fact, HTTPS arguably performs better than HTTP on modern devices.

  3. Using HTTPS means nobody can tamper with the content in your web browser. This was a bit of an abstract concern five years ago, but these days, there are more and more instances of upstream providers actively mucking with the data that passes through their pipes. For example, if Comcast detects you have a copyright strike, they'll insert banners into your web contentall your web content! And that's what the good guy scenario looks like – or at least a corporation trying to follow the rules. Imagine what it looks like when someone, or some large company, decides the rules don't apply to them?

So, how do you as an end user "use" encryption on the web? Mostly, you lobby for the websites you use regularly to adopt it. And it's working. In the last year, the use of HTTPS by default on websites has doubled.

Browsers can help, too. By January 2017, Google Chrome will show this alert in the UI when a login or credit card form is displayed on an unencrypted connection:

Additionally, Google is throwing their considerable weight behind this effort by ranking non-encrypted websites lower in search results.

But there's another essential part required for encryption to work on any websites – the HTTPS certificate. Historically these certificates have been issued by certificate authorities, and they were at least $30 per year per website, sometimes hundreds of dollars per year. Without that required cash each year, without the SSL certificate that you must re-purchase every year in perpetuity – you can't encrypt anything.

That is, until Let's Encrypt arrived on the scene.

Let's Encrypt is a 501.3(c)(3) non-profit organization supported by the Linux Foundation. They've been in beta for about a year now, and to my knowledge they are the only reliable, official free source of SSL certificates that has ever existed.

However, because Let's Encrypt is a non-profit organization, not owned by any company that must make a profit from each SSL certificate they issue, they need our support:

As a company, we've donated a Discourse hosted support community, and a cash amount that represents how much we would have paid in a year to one of the existing for-profit certificate authorities to set up HTTPS for all the Discourse websites we host.

I urge you to do the same:

  • Estimate how much you would have paid for any free SSL certificates you obtained from Let's Encrypt, and please donate that amount to Let's Encrypt.

  • If you work for a large company, urge them to sponsor Let's Encrypt as a fundamental cornerstone of a safe web.

If you believe in an unalienable right to privacy on the Internet for every citizen in every nation, please support Let's Encrypt.

[advertisement] Find a better job the Stack Overflow way - what you need when you need it, no spam, and no scams.
Categories: Programming

Kubernetes: Writing hostname to a file

Mark Needham - Tue, 11/22/2016 - 20:56

Over the weekend I spent a bit of time playing around with Kubernetes and to get the hang of the technology I set myself the task of writing the hostname of the machine to a file.

I’m using the excellent minikube tool to create a local Kubernetes cluster for my experiments so the first step is to spin that up:

$ minikube start
Starting local Kubernetes cluster...
Kubectl is now configured to use the cluster.

The first thing I needed to work out how to get the hostname. I figured there was probably an environment variable that I could access. We can call the env command to see a list of all the environment variables in a container so I created a pod template that would show me that information:

hostname_super_simple.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mark-super-simple-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox:1.24
      command: [ "/bin/sh", "-c", "env" ]      
  dnsPolicy: Default
  restartPolicy: Never

I then created a pod from that template and checked the logs of that pod:

$ kubectl create -f hostname_super_simple.yaml 
pod "mark-super-simple-test-pod" created
$ kubectl logs  mark-super-simple-test-pod
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.0.0.1:443
HOSTNAME=mark-super-simple-test-pod
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
PWD=/
KUBERNETES_SERVICE_HOST=10.0.0.1

The information we need is in $HOSTNAME so the next thing we need to do is created a pod template which puts that into a file.

hostname_simple.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mark-test-pod
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox:1.24
      command: [ "/bin/sh", "-c", "echo $HOSTNAME > /tmp/bar; cat /tmp/bar" ]
  dnsPolicy: Default
  restartPolicy: Never

We can create a pod using this template by running the following command:

$ kubectl create -f hostname_simple.yaml
pod "mark-test-pod" created

Now let’s check the logs of the instance to see whether our script worked:

$ kubectl logs mark-test-pod
mark-test-pod

Indeed it did, good times!

Categories: Programming

SE-Radio Episode 275: Josh Doody on Salary Negotiation for Software Engineers

Marcus Blankenship talks with Josh Doody about salary negotiation. Topics include a framework for thinking about salary negotiations, how you can know what you’re worth, the employers view of salary negotiation, and missed negotiation opportunities. Also discussed are common fears about negotiating and how to overcome them, common mistakes during negotiations, and how negotiation makes […]
Categories: Programming