Remote debugging an embedded WebView in Android

And there I was, thinking that I was done with AzureStorageExplorer for Android v1.0.0. But, nope. In my last round of testing, I couldn’t even login using my work account. The Sign In button didn’t do anything. I went back a few versions to see if the Android update for WebView could have done something to break it. That wasn’t it. The OAuth client library I was using had the recommended code for enabling Javascript in the WebView client so I knew that wasn’t it. I was able to login through the Azure OAuth flow using my personal Azure account. So, I knew there was something about the enterprise account login screen, which could have changed recently that ended up breaking the authentication in the app. It turns out that it did. Read on to know how I found out.

The first step was to prove that something was indeed broken in the login screen for enterprise accounts in Azure in embedded WebViews. To do this, I looked up Chrome’s remote debugging options and found this page describing how to remotely debug WebViews in mobile apps. So, I enabled the setting as recommended by Google, which required adding this piece of code in my activity’s onCreate(Bundle) method.


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}

I ran the app, launched Chrome’s Developer Tools, and connected to the app’s WebView. This is what I found..

2016-12-26_09-49-21

That last error in the console is what was logged when I pressed the Sign In button after entering my work account credentials for Azure. It turns out that the page’s JS now has code to store something in the browser’s localStorage. The reason this isn’t a problem, if you were logging into Azure through a desktop or even a mobile browser, is because localStorage is enabled for every site by default in the non-embedded browser view. But for a WebView in an Android app you need to explicitly enable the DOM storage, just like you need to enable JS through the WebSettings class.

After finding this, it was easy to know where I needed to make the fix. So, I set out to fork the source repo of the OAuth library I was using, made the necessary changes and created a pull request. If you are using the same library and have run into this issue, you could clone my repo and build the project to produce the patched .jar (or an .aar), which you can use in your project directly until the author of the library can get to my pull request (if at all!).

Advertisements

Your options when personal cloud storage services are being blocked…*cough*Turkey*cough*

Official story is here.

I initially wanted to do a comparison of the various cloud storage services and offer some scenario based comparison of when you should use the various providers and some alternatives. But now I wanted to post about a different kind of cloud storage in case you need access to a cloud storage during this period.

It is possible that the sub-domains for the consumer versions of cloud storage services are blocked but not the enterprise/business versions. You may still be able to access these. You can try to use Amazon’s S3 buckets, Azure’s Storage or even Google Cloud Storage. Of course, you could also pay for a VPN service and try to hop around the restrictions. But if you don’t want to pay for a VPN service, you still have this option.

You can create a free developer account with each of those providers:

All of them offer a free month or some sort of credit to use their services so you may not even pay anything until those options run out.

Why enterprise storage?

You get to pick the location of your storage data anywhere where these providers have a data center. This means, you can keep your data within countries in the EU if you wish. Just saying.

Storage pricing

With Azure Storage (https://portal.azure.com), create a Blob Storage type of account and you get to switch pricing tiers between Hot and Cool. Use Cool storage pricing tier for storing large amounts of data and for data that is access less frequently. Use the Hot pricing tier for more frequently accessed data to get better data access speeds. Here’s the pricing page for Azure Storage: https://azure.microsoft.com/en-us/pricing/details/storage/blobs/. The pricing is per GB and the tiers are split in terms of how terabytes of data you are storing. Chances are you will be within the 100TB tier. For an example, let’s say you have the said leaked emails, they are possibly less than 100GB. You will pay ~$2 USD a month for storage and data retrieval is free for the Hot pricing tier. My recommendation is to use the Hot tier to start with and then when you are not access the data as much, switch to the Cool tier then to save money on storage.

With AWS S3, you can opt for Reduced Redundancy storage for a much lower cost (almost free). https://aws.amazon.com/s3/reduced-redundancy/. Here’s a total cost of ownership calculator from AWS https://aws.amazon.com/tco-calculator/ to help you decide.

Useful apps for accessing enterprise storage

S3 explorer (Windows; unofficial): http://s3browser.com/

S3 explorer for Android (unofficial): https://play.google.com/store/apps/details?id=lysesoft.s3anywhere&hl=en

Azure Storage Explorer (official): http://storageexplorer.com/

Azure Storage Explorer for Android (BETA; unofficial): https://play.google.com/apps/testing/com.pl.azurestorageexplorer

Disclaimer: The Azure Storage Explorer for Android is my own app that I have been working on. It is completely free, open source and ad-free.

It is time to give

Disclaimer: This post is not meant to guilt-trip you into signing-up for anything. Just an informational post about something nice happening during the weekend of 10/14.

A few years ago, I was asked if I would volunteer to help build a software for a cause. That was when I was living in Indiana. I participated in the Indy GiveCamp. I helped build a mini-CRM over a weekend for a dance studio operated by women for women. Of course, it wasn’t just me building the application. We were a team of 4. Coming out of the weekend, it was the best feeling ever, of being able to help someone’s cause with my programming skills. I didn’t even spend a dime. It sounds  simple, doesn’t it? These organizations that need help with IT don’t want your money, they want YOU. Your time and help is all that they would like to get for that ONE weekend.

Fast-forward 2 years and I now live in the Seattle area. There is a Seattle GiveCamp happening during the weekend of 10/14. I am going. I even convinced someone I work with, a friend of mine, to sign-up as well. We couldn’t be more excited. I am looking forward to meeting new people, hearing about their causes and cranking out code.

Learn more about GiveCamp and the Seattle GiveCamp. Find out if there is one happening in your city and sign-up. Do it. And take your friends with you too.

Image

Unofficial Tesla Android client for controlling your Model S

Tesla Motors

Tesla Motors

GitHub link: https://github.com/praneetloke/MyTesla

But there’s already an official app from Tesla for the iOS and Android, then why this? Because I wanted to and besides there aren’t any open source Android clients. There are couple of Ruby clients and a node.js client. The node.js client is particularly of interest to me since it has visual examples of each API it supports. The telemetry streaming API is my favorite. If you remember, that’s what Tesla used to debunk the NY Times reporter for his fake report on the Model S sometime ago.

Anyway, back to the MyTesla client. You can fork it, download it, modify it, do whatever you want with it. This client is unstable, unofficial, and most importantly, unverified (since I don’t own a Tesla Model S, unfortunately). So please use this with caution. If you find bugs, please raise an issue in my repo or you can fork-fix-pull. If you are able to help with its stabilization by testing this on your Tesla Model S, please let me know. You can hit me up on G+ or LinkedIn.

There are 3 REST API clients for your use in this project. LoginClient, VehicleStatusClient and VehicleCommandClient. I have already pulled in these 3 REST interfaces into a custom Android Application class called TeslaApplication. I did this to remove any dependency from consumers having to pull in AndroidAnnotations as well. On a side note, you should check out AndroidAnnotations. It is awesome! Anyway, in your project, you can simply extend the TeslaApplication and be on your way. You don’t need to put anything in it. I have not actually tested to see if such an extension is actually required if you were to reference this project but be my guest.

I have also made a LoginActivity which has a boilerplate login form which you can present to your users. It handles submitting the email and password to the API and inspecting the response to see if it was successful. I actually plan to change this to a login dialog instead or perhaps have both since a dialog only needs a layout. Then you can choose either depending on your needs. When login fails, it currently doesn’t do anything. I am yet to work on that. I also need to work on some cookie transfer from LoginClient to the other two clients because from what I saw in the AndroidAnnotations sources, there doesn’t seem to be a unified storage for cookies acquired by REST interfaces.

When you look at the library I made, you will notice that I didn’t use primitives. That’s because of the nature of the API itself. It’s unofficial and there are unconfirmed properties whose values are unknown and sometimes null. So this being Java, I couldn’t use primitives in some cases. For those that had confirmed values I could have used primitives but I felt I needed to be consistent rather than have you guess what you’ll be using when you inspect an object. And yes, I am talking about primitives and objects because I actually went ahead and created model classes (POJOs) for all of the endpoints. This should make interaction way easier. It uses Gson for type conversion. I chose Gson over Jackson mapper for its lightweight and performance. Gson doesn’t have all of the features Jackson has but it does the job, fast too.

If you have watched this clip of the guy issuing commands to a Tesla Model S, you’ll be at least half as excited as I was to find a REST client and play with it if you have a Tesla Model S. Of course, you would more likely already have the official Tesla app. But if you are into programming and diving into things on your own, this is for you. I wish my VW CC was capable of something like this.

Credits

  • Tim Dorr (and many others that commented on each API endpoint in the Apiary blueprint) for his excellent Apiary documentation based on his findings. He has implemented his very own ruby implementation of the API here.
  • AndroidAnnotations
  • Spring Android

Other clients

  • node.js
  • Ruby. For Ruby, there’s also the one from Tim Dorr himself.

My struggles with Android’s CalendarContract introduced in ICS

While working on some upgrades for Squiggly I wanted to subscribe to Android’s calendar provider events. This is how you would do it.

Assuming you have a receiver in your app, if you have declared it in the manifest xml, then add this to get provider_changed intents. Thanks to this stackoverflow question.

<intent-filter>
    <action android:name="android.intent.action.PROVIDER_CHANGED"/>
    <data android:scheme="content"/>
    <data android:host="com.android.calendar"/>
</intent-filter>

Now, the above intent-filter is missing a few things that could have made my interaction with the calendar provider easier. They are the attributes paths, pathPattern and pathPrefix for the “ part of the intent-filter. Unfortunately, even specifying those attributes won’t do you any good because the CalendarProvider class itself doesn’t specify those parameters on the intent that is fired from within.

The other problem is that the intent that is fired from CalendarProvider doesn’t even carry the event id that is passed to it from the methods that call it. See sendUpdateNotification from CalendarProvider2.java in the JellyBean source code here. This method sends a message to its Handler instance which then broadcasts the intent for provider_changed action. ref: this line. The problem is this simply obtains a message from the message pool and passes the value that sets the what of the Message instance returned. Instead, they could have done this:

//get a message using the obtainMessage(int what, Object obj) version
Message msg = mBroadcastHandler.obtainMessage(UPDATE_BROADCAST_MSG, new Long(eventId));

With the eventId now getting lost with the aforementioned line#4478 from CalendarProvider2.java, the handler now doesn’t even add any extras to the intent before broadcasting it. The control eventually reaches doSendUpdateNotification, which as you can see does nothing but set the action in the intent and broadcasts it.

What’s even more frustrating is that if you look at the usages of this method, the callers actually do pass the eventId and the actions that trigger a call to this method are actually the ones I want to know the event ID for!!

Usages for sendUpdateNotification in JellyBean r1

Usages for sendUpdateNotification in JellyBean r1

Well, looks like the latest KitKat revision still hasn’t changed this. Until then, I guess I will have to scan the instances table whenever the provider_changed action is received. 😦

If you care about this issue and want to bring this to the Android team’s attention then please vote for this issue.

Dynamic entries in Android’s MultiSelectListPreference

So I was finally excited that my brother and I decided to drop support for Gingerbread for the next iteration of Squiggly and that allows me to do things like use the MultiSelectListPreference and use the local Calendar API exclusively.

But there is a drawback with MultiSelectListPreference. You have to pre-define the string arrays for entries and entryValues. This sucks. This is why I have now added CustomMultiSelectListPreference to CustomPreferences. I have followed the same pattern which I did with CustomListPreference by implementing the IDynamicProvider which I introduced a while back when I needed to populate a regular list preference dynamically.

This is the class to reference in your preference xml file.

To use it:

<com.myappfactory.preferences.CustomMultiSelectListPreference
            android:key="@string/calendarsToMonitorKey"
            android:dependency="@string/enableCalendarBackgroundServicesKey"
            android:title="@string/calendarsToMonitorTitle"
            android:dialogTitle="@string/calendarsToMonitorDialogTitle"
            android:summary="@string/calendarsToMonitorSummary"
            customPreference:dynamicEntriesProvider="your.app.package.ClassThatImplementsIDynamicProvider"
            customPreference:dynamicEntryValuesProvider="your.app.package.ClassThatImplementsIDynamicProvider"
            customPreference:selectAllValuesByDefault="true"
            android:entries="@array/empty_array"
            android:entryValues="@array/empty_array"
            android:defaultValue="@array/empty_array"/>

selectAllValuesByDefault does exactly what it says. It selects all the values that are dynamically added. The class that provides these dynamic entries and entryValues need to implement IDynamicProvider. The no-argument version of populate method will no longer be supported. So be sure to implement the populate that accepts a Context. CustomMultiSelectListPreference first calls populate then calls getItem. I have tried to keep the same naming convention that Android’s adapter classes use. So you will see getCount and getItems in there.

Here’s a preview of what it will look like:

CustomMultiSelectListPreference

CustomMultiSelectListPreference

Video

Transitions 1.3.1

v1.3.1 is out of Beta! I have finally pushed v1.3.1 to Production. You can get it here.

I am also taking a hiatus from updating Transitions for a while unless there are critical bugs to fix. I will be shifting my focus to refactoring Squiggly.

Here’s a preview of what v1.3.1 has to offer. Of course, keeping up with the mantra of Transitions, it’s all free, no ads.

Assassin’s Creed IV for $14!

I just secured a copy of Black Flag from BestBuy for $14! Holy crap! See this if you don’t believe me.

Ford TDK

Guess what?? Last week, I got the Ford TDK which I won from participating in an app idea contest held by Ford. Here’re the pictures!

TDK power cord and instructions manual.

Instructions and power cord for the Ford/Lincoln TDK 3.0

Ford/Lincoln TDK

Ford/Lincoln TDK

Triumph Daytona TechSpecs C3 TankGrips and Puig Race Windscreen

Love these tank grips! I bought them off the Triumph675 forums from the forum sponsor Riders Discount. I bought the Puig windscreen from the same folks. Good service.

Triumph Daytona

My 2010 Triumph Daytona