Tuesday, April 18, 2017

How to use java.time in Android

Java 8's java.time package (a.k.a. JSR-310) is very useful for dealing with timestamps and timezones, etc.  But at the time of this writing, the Android SDK only includes Java 7, so the java.time package is not available to Android projects.  There are alternative libraries out there for working with time, such as Joda-Time or Date4j, but they have various shortcomings, and java.time is regarded to be the standard going forward. Fortunately, JSR-310 has been backported to Java 7 and 6 by Stephen Colebourne & Michael Nascimento Santos (http://www.threeten.org/threetenbp/). 

However, you shouldn't simply grab the main threetenbp jar and add it to your Android project, because it includes the olson time zone database in its jar file, and in Android, loading resources from jars has a huge memory overhead.  Instead, include the no-tzdb.jar, which does not include the database.  And then, use Jake Wharton's ThreeTenABP aar, which provides the database to ThreeTenBP as an Android resource, much more efficiently.   

If you're using mavenCentral (the default) include the following in your module's build.gradle file, in the dependencies section:
    compile 'com.jakewharton.threetenabp:threetenabp:1.0.5'
If you prefer to work offline, you can do the following:

obtain or build a copy of the com.jakewharton.threetenabp aar and the org.threeten.threetenbp no-tzdb jar
put the no-tzdb jar in a folder named "libs" in the root of your module project
put threetenabp aar file in a folder names android-libs in the root of your module project.
include the following lines in your build.gradle file:

    allprojects {
        repositories {

            flatDir {
                dirs 'android-libs'
            }

        }
    }


    ...
    dependencies {

        compile fileTree(include: ['*.jar'], dir: 'libs')
        compile(name: 'threetenabp-x.x.x', ext: 'aar')

    }


Then in your java code, where you would use
import java.time
just use
import org.threeten.bp
and you can use the Java 8 time APIs in your Android project!

Wednesday, June 19, 2013

5 Reasons you should fight for privacy even if you have nothing to hide

In the national discussion that arose in the wake of the revelations about NSA's PRISM program, I've heard many people say something to the effect of, "I don't break any laws, so I have nothing to hide. Why should I care?" Well here's why:


1. Not doing anything wrong is not the same as having nothing to hide

Data collection and analysis can bring harm to people who lead exemplary lives. If you run a business, or work at one, you have trade secrets and clients to protect. If you run for political office, you have campaign strategies that your opponent would love to know. If you are a journalist, you have sources to keep anonymous. And we all have stuff that someone would like to steal. Information collected from your online communications could give a business or political rival an unfair advantage against you, or could be used by an unethical person to construct a detailed and highly deceptive phishing attack to obtain passwords or other information, or could be used to determine when a home or business is unattended and vulnerable to break-in.

But the NSA's not going to do be doing any of that kind of stuff right? Probably not. But it's not the NSA, per se, that we need to worry about....


2. Hackers

You may trust the American government with all the intimate details of your life, but how about the Chinese Government? China has repeatedly gained access to Top-Secret information held in government systems. What about a hacker group like Anonymous? Or the Russian mafia?


3. Rogue Employees

There are policies in place designed to prevent information from being leaked, but are you absolutely certain that the employees who have access to your private information will obey their employers' policies? Edward Snowden didn't. He broke policy for idealistic reasons but there's no guarantee the next leaker won't have more nefarious purposes.
It is a law of human nature that all power will be abused at some point. Remember when we learned that the IRS was targeting conservative groups? Or that Mark Zuckerberg broke into the Email accounts of rivals and journalists? Or that members of Congress routinely trade stocks based on insider information? The information PRISM collects will be abused as well.


4. Regime Change

Today's government may be trustworthy, but our government is guaranteed to change hands. And the next administration inherits all the information collected by the previous ones. Are you certain that in the next election those loonies on the other side of the aisle won't get the votes they need to put immoral/incompetent people in charge of everyone's information?


5. It's not just about you

Maybe you think privacy doesn't matter to you because you're too insignificant - you don't have any money or important information, and you never do anything improper or embarassing. But what about the people you know? What about your friends, family members, or co-workers? Information about you can be used to get to them. It is important that we protect the people who ARE potential targets - political candidates, activists, business owners, judges and attorneys, members of the military, etc...


Just in case you haven't already realized it - every one of these arguments applies not just to the government, but to the corporations that collect this information in the first place. The potential for abuse seems much more likely by an employee of Microsoft or Google or Apple than by a vetted government contractor - and we already know THAT has happened. The solution to this issue is not for the NSA to stop getting information from service and content providers - it's for the service providers to stop collecting the information in the first place.

Wednesday, May 8, 2013

A tool for working with bi-directional text



working with bi-directional text can be ...um... interesting.  Ok, bloody frustrating.  Especially on a Mac.

At times I've found it necessary to use the unicode bi-directional formatting characters in order to get certain combinations of English and Arabic to display properly in Flex.  (btw, If you don't know what bi-directional formatting characters are,  there's a great explanation at http://www.iamcal.com/understanding-bidirectional-text/)  Unfortunately, those are zero-width characters, which makes them difficult to deal with in a standard text editor.

So I made myself a little tool that makes it easy to detect and insert bi-directional formatting characters in a block of text.  It's not what I would call slick, but I've found it helpful, so maybe someone else will too.  You can give it a try here: http://www.dougmccluer.com/bidiedit/

Basically you paste some text in the top box and in the bottom it will display all the unicode codes for each character.  The bidirectional formatting characters are called out in the bottom box with a special syntax.  You can switch between LTR and RTL display, and surround a selected run of text with the bidi-formatting characters of your choice.

If you know of a good cross-platform app for controlling the appearance of bi-directional text on a line-by-line basis, let me know in the comments!

Friday, September 7, 2012

How to embed assets in Flash Builder 4.7 Actionscript Projects

In Flash builder 4.7, [Embed] metadata tags are handled differently depending on whether you're working on a Flex-based project, or a pure actionscript one.  One difference has to do with how the path in a source attribute is looked up.

In a Flex project if you create a tag like this:
 [ Embed(source="myAsset.png") ]
the compiler will look for a file called myAsset.png in the root project folder.  This is the behavior Flash Builder users are accustomed to.

But in an actionscript project, the compiler will search for it relative to whatever folder the actionscript file is in. So let's say I have an actionscript class in package com.dougmccluer.controls.customList.as.  And in that class, I embed a graphic like so:
[ Embed(source="myAsset.png") ]
I will need to place my graphic file at [project root]/src/com/dougmccluer/controls/myAsset.png

OR, if I want to place my graphics in a folder called "embeds", I can change my metadata tag to look like this:
 [ Embed(source="../../../embeds/myAsset.png") ]
Absolute paths are also acceptable, for example:
/Users/doug/projects/testProject/embeds/myAsset.png
C:/Users/doug/Documents/projects/testProject/embeds/myAsset.png
but keep in mind absolute paths are not very friendly for collaborative projects.

If you use relative paths, you must update the paths any time you move the actionscript file.

Hopefully, by the time this product leaves beta, the actionscript compiler will be brought back in line with the Flex compiler so that they both interpret Embed paths as relative to the project folder.  

Wednesday, April 25, 2012

How to Make Flash Builder Start When it Won't Start



 Recently I've been working with Flash Builder 4.6 on Mac OSX 10.7 a.k.a. Lion.  A couple times now I've encountered a problem where Flash Builder just won't start.  It just hangs at the splash screen and the little beachball spins away.

Through Googling, I learned that other people have encountered the same behavior and they fixed it by deleting a .metadata file in their workspace. Supposedly the issue was that the workspace had become corrupted.

I could not find a .metadata file, but I was able to get running again by doing the following:

  1. Shut down (force quit) Flash Builder.
  2. Rename the workspace folder.
  3. Start up Flash Builder.  Behold!  It starts!  All the projects are now broken because the paths are now incorrect.
  4. Shut down Flash Builder.
  5. Rename the workspace folder back to what it was.
  6. Start up Flash Builder.
  7. Breathe a sigh of relief.

Hope this helps someone out.



Sunday, April 22, 2012

How to get scale9 images into Flex from Photoshop a little easier

Really getting into Flex skinning for the first time, and having been a Flash Professional guy for years, I'm  unenthused by what a cumbersome, non-visual process it is.

Case in point: the scale9 grid.

To use a scale9 grid on an embedded image you manually enter the pixel locations of the edges of the grid, like so:

<s:Image source="@Embed(source='embeds/myImage.png' scaleGridLeft='12', scaleGridTop='9', scaleGridRight='550', scaleGridBottom='63' )"/>

Much less convenient than the GUI that Flash Pro provides.  So I wrote a little extendScript to reduce the amount of time I spend measuring pixels in Photoshop.  It works like this:

1. Draw a selection box to define the area that should be the middle box in the scale9 grid.
2. Run the script.
3. Copy the text from the popup window and paste it into your Embed code

The code is below:

function getBounds(){}

getBounds.prototype.run = function()
{
 var selBounds;
 if(activeDocument.selection)
 {
  selBounds = activeDocument.selection.bounds;
 }
 else
 {
  alert("no selection");
 }
 var left = selBounds[0];
 var top = selBounds[1];
 var right = selBounds[2];
 var bottom = selBounds[3];
 
 // Create the palette-type window (a modeless dialog)
 var win = new Window('dialog', 'getBounds');
 this.windowRef = win;
 win.bounds = [100,100,760,260];
 
 // Create a container panel for the components
 win.pnl = win.add("panel", [5,5,650,150]);

 win.pnl.txt = win.pnl.add('edittext', [15,15,630,65], "scaleGridLeft='"+left.value+"', scaleGridTop='"+top.value+"', scaleGridRight='"+right.value+"', scaleGridBottom='"+bottom.value+"'");

 win.pnl.okBtn = win.pnl.add("button", [25,110,105,130], 'OK');

 // Define the behavior of the buttons
 win.pnl.okBtn.onClick = function()
 {
  win.close();
 }
 
 // Display the window
 win.show();
return true;
}

new getBounds().run();

Download the script file

To install the script, copy it into Photoshop's Scripts directory
Windows: C:\Program Files\Adobe\Adobe Photoshop CS4\Presets\Scripts\
Mac OSX: Applications/Adobe Photoshop CS4/Presets/Scripts/
After you restart Photoshop, it should appear under File > Scripts > GetScaleGridDimensions


I'm sure there's an even better solution out there, I'm just not aware of it.  If you are, let me know about it in the comments.  :)

Friday, April 20, 2012

Testing a Flex App for the iPad3 (part 2)



When testing a Flex app for the iPad3, you'll want to create a custom RuntimeDPIProvider so that the app scales to the correct size.  The Adobe docs describe how to subclass RuntimeDPIProvider at http://help.adobe.com/en_US/flex/mobileapps/WS19f279b149e7481c682e5a9412cf5976c17-8000.html#WS19f279b149e7481c-2a25e9b212d622ff5e8-8000

Using the following class will ensure the app is sized correctly on the device (using both slow and fast compile methods) and when previewing on the desktop.

package com.dougmccluer
{
 import flash.system.Capabilities;
 import mx.core.DPIClassification;
 import mx.core.RuntimeDPIProvider;
 
 public class CustomRuntimeDPIProvider extends RuntimeDPIProvider
 {
  public function CustomRuntimeDPIProvider()
  {
   super();
  }
  
  override public function get runtimeDPI():Number
  {
   if(Capabilities.os.indexOf("iPad")>-1)
   {
    if(Capabilities.screenResolutionX > 1500)
    {
     return DPIClassification.DPI_320;
    }
   }
   return DPIClassification.DPI_160;
  }
 }
}

You just need to tell the application to use the custom runtime provider and set the application dpi to 320.

s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  applicationDPI="320"
  runtimeDPIProvider="com.dougmccluer.CustomRuntimeDPIProvider">