Tag: Google

Programming Stuff

Google Cloud Printing from Android

If you’ve worked with Google Cloud Printing then you know that much of the sample code out there that shows how to submit print jobs using Java or C# don’t work … frustrating to say the least.

After more pain then I’d care to admit, I finally got the code working so wanted to share it.

Below is the code to submit a PDF file for Printing (or storage on a Google Drive) using Google Cloud Printing from an Android device.

For a complete Android Studio project that shows how to interrogate the available printers, get the list of print jobs, and submit a print job download this project zip file.

public class GoogleCloudPrint {
 private static final String SERVICE_SOURCE_NAME = "your-apps-name-for-logging-purposes";
 public static final String GCP_BASE_URL_STRING =
  "https://www.google.com/cloudprint";
 private static final String SUBMIT_URL_STRING =
  GCP_BASE_URL_STRING + "/submit";
 private static final int DEFAULT_STREAMING_CHUNK_SIZE = 0;
 String mUsername;
 String mPassword;
 public GoogleCloudPrint(String username, String password) {
  mUsername = username;
  mPassword = password;
 }
 public void print(String printerId, String title, File documentFile, String mimeType) {
  try {
   byte[] documentBytes = getBytes(documentFile);
   String urlString = SUBMIT_URL_STRING +
    "?output=json" +
    "&printerid=" + printerId +
    "&contentType=" + mimeType +
    "&title=" + title ;
   // Open connection and configure for POST with streaming writes
   HttpsURLConnection connection = createConnection(urlString);
   connection.setDoOutput(true);
   connection.setChunkedStreamingMode(DEFAULT_STREAMING_CHUNK_SIZE);
   // Create the multi-part form data prefix and suffix
   // include filename value in prefix
   String queryPrefix = String.format(
    "------CloudPrintFormBoundaryqeq6g6ncj5v7\r\n" +
    "Content-Disposition: form-data; name=\"content\"; filename=\"%s\"\r\n" +
    "\r\n", title);
   String querySuffix = "\r\n------CloudPrintFormBoundaryqeq6g6ncj5v7--";
   // Encoide prefix and suffix and determine total content length
   byte[] queryPrefixBytes = EncodingUtils.getAsciiBytes(queryPrefix);
   byte[] querySuffixBytes = EncodingUtils.getAsciiBytes(querySuffix);
   int contentLength = queryPrefixBytes.length + documentBytes.length + querySuffixBytes.length;
   // Add headers for multipart form data and length
   connection.addRequestProperty("Content-Type", 
    "multipart/form-data; boundary=----CloudPrintFormBoundaryqeq6g6ncj5v7");
   connection.addRequestProperty("Content-Length", Integer.toString(contentLength));
   // Write the document to server wrapped as multipart form data
   writePrintBody(connection, queryPrefixBytes, documentBytes, querySuffixBytes);
   // Write results to log
   InputStream inStream = connection.getInputStream();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 private HttpsURLConnection createConnection(String urlString) throws IOException {
  String auth = retrieveAuthToken(mUsername, mPassword);
  URL url = new URL(urlString);
  HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
  connection.addRequestProperty("X-CloudPrint-Proxy", SERVICE_SOURCE_NAME);
  connection.addRequestProperty("Authorization", "GoogleLogin auth=" + auth);
  return connection;
 }
 private void writePrintBody(HttpsURLConnection connection, byte[] prefixBytes,
  byte[] documentByes, byte[] suffixBytes) throws IOException {
  OutputStream outStream = new BufferedOutputStream(connection.getOutputStream());
  outStream.write(prefixBytes, 0, prefixBytes.length);
  outStream.write(documentByes, 0, documentByes.length);
  outStream.write(suffixBytes, 0, suffixBytes.length);
  outStream.flush();
  outStream.close();
 }
private String retrieveAuthToken(String userId, String password) {
  final String AUTHORIZE_URL_FORMAT = "https://www.google.com/accounts/ClientLogin" +
   "?accountType=HOSTED_OR_GOOGLE" +
   "&Email=%s" +
   "&Passwd=%s" +
   "&service=cloudprint" +
   "&source=" + SERVICE_SOURCE_NAME;
  String authorizeURL = String.format(AUTHORIZE_URL_FORMAT, userId, password);
  String auth = "NOT_SET";
  InputStream inStream = null;
  BufferedReader reader = null;
  try {
   URL url = new URL(authorizeURL);
   HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
   inStream = connection.getInputStream();
   reader = new BufferedReader(new InputStreamReader(inStream));
   String buffer;
   StringBuilder stringBuilder = new StringBuilder();
   while ((buffer = reader.readLine()) != null) {
    String[] parts = buffer.split("=");
    if ("Auth".equalsIgnoreCase(parts[0])) {
      auth = parts[1];
      break;
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    if (reader != null)
     reader.close();
    if (inStream != null)
     inStream.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return auth;
 }
 private byte[] getBytes(File documentFile) {
  byte[] bytes = null;
  try {
   FileInputStream inputStream = new FileInputStream(documentFile);
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   byte[] buffer = new byte[4096];
   int n = inputStream.read(buffer);
   while (n >= 0) {
    baos.write(buffer, 0, n);
    n = inputStream.read(buffer);
   }
   inputStream.close();
   baos.flush();
   bytes = baos.toByteArray();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return bytes;
 }
}
Programming Stuff

AnDevCon Slides and Code

Thanks to everyone for attending the AnDevCon Tutorial and Class this week. Here’s the info from both.

Understanding Android Studio and Android Developer Toolset

Integrate Google Cloud Printing Into Your Android App

You must set the user id and password constants in the GmailHelper class or the program will not work

Thank you to everyone who attended. Please feel free to contact me with any questions.

ADCLogo_large

Programming Stuff

Android “Master Key” Security Patch Check Available

Odds are that you’ve heard about the security hole that was found to exist in virtually all Android devices that would allow someone to take control of the device.

The good news is that Google has created a patch for the issue and sent it to OEMs. The challenge always comes down to the OEMs getting the patch distributed to our phones and, as always, that is taking time.

It turns out that we can all check to see if we have the patch installed thanks to Bluebox (the folks who discovered the problem) releasing a free app that will check your phone to see if you have the patch.

Although the app is not able to apply the patch because that’s up to the OEM of your device you can at least know where you stand and if you are so inclined start complaining to your carrier that you’d like them to work with the OEM and hurry to get it distributed.

Programming Stuff

Android Studio Dark Theme (Darcula)

After seeing those cool demos of Android Studio showing the neat-looking dark theme, the default theme that Android Studio downloads with can be a little disappointing.

If you haven’t seen it, here’s Android Studio set to the Darcula theme.

Android Studio Darcula Theme

To get the Darcula theme, first open the Android Studio Settings dialog

  1. Select File on the Android Studio menu
  2. Then select Settings

Once on the Settings screen just…

  1. Highlight Appearence
  2. Click on the Theme dropdown and select Darcula
  3. Click OK

Setting Darcula Theme

You’ll be prompted to restart Android Studio. Allow the restart and there you have it. The great look of Android Studio in Darcula.

Adapted from Jim’s Pluralsight course Android for .NET Developers: Getting Started

AndroidDotNetSeries_GettingStarted_Logo

Programming Stuff

Android for .NET Developer Series: Getting Started

There’s no question that smartphones and tablets have become the computers of choice for most users. Android has been the leading smartphone for some time and now Android leads in tablets as well.

According to Google, nearly 900 million Android devices have been activated. This presents an incredible opportunity for both individual developers and organizations to create software with a reach and impact beyond anything previously possible.

Android development is, of course, very different from the web-based and/or desktop app development most of us have been doing for years. But this difference doesn’t mean we can’t take part in such a great opportunity.

People will often point to Android’s use of Java rather than .NET being the biggest challenge in becoming an Android developer. I disagree. If that were the case, environments like Mono that enable the use of C# and .NET libraries on Android would enable us all to immediately become Android developers. But in my experience, developers with a .NET background who use Mono don’t become effective Android developers any faster than those who take the plunge and use Java. Why is that?

The challenge in creating Android apps is not the programming language, class libraries, or runtime. The challenge in creating Android apps is that it’s an entirely different way of thinking and an entirely different approach to application development.

To be successful on such a different platform, developers need to adopt and ultimately embrace the way-of-thinking of the Android platform.

The new series from Pluralsight, Android for .NET Developers, strives to do exactly that. We focus on guiding developers to fully embrace the tools, language, libraries and, most importantly, mindset of Android development by building on your skills as a .NET developer. Although this series assumes a .NET background, the series is appropriate for anyone with existing programming experience who wants to start working with Android.

In the first course in the series, Android for .NET Developers: Getting Started, we walk through the process of setting up your environment, using the Android development tools, and deploying apps to both real devices and emulators. We talk briefly about the long-standing development environment, Eclipse, but focus throughout the series on the new development environment, Android Studio, announced by Google just a few days ago.

The first course in the series is now available with a new course from the series being released every few weeks. The series is made up of the following courses.

Android for .NET Developers: Getting Started

Android for .NET Developers: Building an Android App

Android for .NET Developers: Android data management

Android for .NET Developers: Adopting the Android mindset

Android for .NET Developers: Embracing the Android platform

I hope you’ll join me in this experience of leveraging your existing skills to empower you to take part in the opportunity offered by the success of Android. At the end of this series, I’m confident that you will have adopted the Android mindset and will be embracing the Android platform.

Android for ,NET Developer Series: Getting Started

Programming Stuff

Android Meetup May 2013 – Android Camera Integration

Thank you to everyone who attended the Central Florida Android Developers Group last night. Special thanks to Echo for hosting the event.

I had the opportunity to talk about how to easily integrate photo capture capability into one’s app by leveraging the built-in Android camera app and Intents.

Last night’s presentation was an excerpt from the first module of my Android Photo and Video Programming course.

You can download the code from last nights discussion. The download includes the Photo capabilities we discussed and also includes Video capability, which we didn’t have time to discuss. Please feel free to post any questions you might have.

For more information on this and other Android-related topics, checkout Jim’s Android courses at Pluralsight.

PSAndroid_216x155

Programming Stuff

Can’t find Developer Options on Android 4.2

Ok so this has to be among the silliest UI “innovations” I’ve encountered.

After updating my phone, Samsung Galaxy Nexus, to Android 4.2.2, I could no longer find the Developer Options menu. And here’s why … Google seems to have decided to no longer make that menu visible by default.

We can argue over why they made such a change ( my guess is to make the developer options less accessible to non-devs ) … but whatever the reason, it’s a pain.

So how to get it back ? (you’re not gonna believe this) …

  1. Open your settings menu
  2. Scroll down and select “About phone”
  3. Locate the entry labeled “Build number’ (probably near the bottom)
  4. Tap repeatedly (I believe its 7 times) on the “Build number” entry  (I’m not making this up)
  5. As you do you’ll eventually see a message something like “You are now X steps from being a developer” … continue to tap until the “Developer Options” menu become visible.

And now you have your “Developer Options” menu back … it’ll appear on the Settings menu (screen just prior to reaching the screen with the “Build number” value)

Kind’a crazy … ain’t it

Checkout other Android Developer related information from Jim in his courses from Pluralsight.

PSAndroid_216x155

Programming Stuff

Avoiding Android App Crashes Caused by Device Orientation Changes

A challenge commonly faced when first developing in Android is the potentially frequent destruction and reconstruction of an Activity. The most common time this occurs is when the user rotates the device between horizontal and portrait orientations.

Many an app that runs fine during testing suddenly crashes when put into a user’s hands simply because the user tilted the device one way or another.

This crashing usually occurs because device orientation changes cause the Android framework to tear down the displayed Activity along within any contained Views, and then to fully reconstruct the Activity/View hierarchy. Any references to the Activity or to the Views within the Activity suddenly become invalid. Similarly any references within the Activity or Views that were set as a result of a user action or similar are now lost.

There are a number of ways to deal with this issue but one of the easiest is to take advantage of Fragments.

NOTE: You can use the configChanges attribute on your Activity’s manifest entry to prevent the teardown/reconstruction process caused by orientation changes but that has its own headaches.

Fragments won’t automatically resolve this issue because, by default, when the Activity is torn-down in response to an orientation change the Fragment contained within the Activity is also torn down along with any contained Views.

The solution lies in an underused method: Fragment.setRetainInstance.

Calling setRetainInstance with a value of true causes Android to preserve the Fragment across the teardown/reconstruction cycle of an Activity. Along with the Fragment, the Views or other object references contained within the Fragment or Views remain.

With setRetainInstance(true) called on a Fragment instance … when an orientation change occurs, Android…

  1. Holds a reference to the Fragment instance
  2. Tears down the old Activity instance
  3. Creates a new Activity instance
  4. Attaches the preserved Fragment instance to the new Activity instance

With that, the Fragment, contained Views and object references, remain intact.

Something to keep in mind though … because your Fragment instance will be moved between different Activity instances, you should avoid caching a reference to the Activity. Instead call Fragment.getActivity anytime you need to reference the Activity.

Jim talks more about Fragments in his Pluralsight course…

AndroidFragments_400x100

Programming Stuff

Android 4.x jumps from 45% of Android devices to nearly 55% overnight

That’s right if you look at the Android Dashboard Charts for the current period (period ending April 2, 2013 as of this writing) you’ll find that the combination of 4.0, 4.1, & 4.2 devices is 54.3%.

AndroidChart_2013-04-02

If you looked at the chart for the previous period you find that same family of devices had only 45% of all Android devices. How does one account for such a huge jump?

Well – one way is to change the way one counts. 🙂

You’ll find the following note on the Android Dashboard Page:

Note: Beginning in April, 2013, these charts are now built using data collected from each device when the user visits the Google Play Store. Previously, the data was collected when the device simply checked-in to Google servers. We believe the new data more accurately reflects those users who are most engaged in the Android and Google Play ecosystem.

So basically .. they now count devices that actually attach to Google Play rather than counting every single device that just happens to wake up periodically and send a heartbeat to the Google servers.

So the cynic might say that Google is skewing things for their own advantage (I’m not saying they’re unhappy with this new way of counting) but I don’t really think that’s the case here.

Honestly, most of us looking at those charts are interested in seeing what versions of the platform we should target with our apps. Those apps are distributed via Google Play … so, I agree that this is the “right way” to count.

For information on creating apps for Android 4.x, checkout Jim’s Pluralsight Course

Android40WhatsNew_350x100