Monday, October 9, 2017

The Problem - Registering connectivity change when targeting API 24+

Not all Android Broadcasts are created equally and you can't create them in the manifest in all cases. There are some you must configure at runtime because of changes Google made to apps targeting N (API 24).

From the documentation: Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare their broadcast receiver in the manifest.

The Solution

The docs are not as clear how to handle this, so here is the code to allow your app to still receive connectivity change broadcasts after targeting N or later:

public void onCreate() {

...

//Change 'YourConnectionChangedBroadcastReceiver' to the class defined to handle the broadcast in your app

I'd also recommend removing the declaration from AndroidManifest.xml as if you leave it in there, it will actually create multiple instances of your broadcast receiver.

<receiver android:name="YourConnectionChangedBroadcastReceiver">

<intent-filter>

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

</intent-filter>

</receiver>

Registering it programmatically unlocks the receiver for use by your app (including those for CONNECTIVITY_ACTION in your manifest), and that's all there is to it. You can save the registered receiver instance and unregister it when no longer needed, however, this is not necessary if it lasts the entire lifetime of your application.

Saturday, June 25, 2016

The Background

Test your backwards IQ in this indie trivia game. I developed this game in Unity3D with a friend of mine, Don. We came up with the idea of having a trivia game where you would know all the answers but all of the logic is reversed. The result is quite fun and is especially challenging in cases where what is being asked is negative. For example: Don't click on the red circle.

Filling out questions to tempt the user into a wrong answer was almost as fun as playing the game. The sliding bar quickly disappears giving the user a sense of urgency and you will make mistakes playing this game.

The Game

What you know won't help you, because every answer you know is wrong. Some times it's not as easy to answer as you think.

Check out the game and let me know you feedback. Is it good, does the game annoy you? Whatever. Check it out and have some fun with it.

Thursday, April 14, 2016

When you are looking at data it can be helpful to place it into categories based using what I call a category tree breakdown. This can give us additional information that may not be apparent without looking at the breakdown.

In this simple example, say we have gathered a simple dataset on various political candidates, including: First Name, Last Name, Party Affiliation, Gender, State Affiliation, and Job. Maybe we would want to see which genders were associated with which jobs or what the similarities are across party or state affiliations.

Each of these could be done individually in SQL, but that would be inefficient and wouldn't expose the power of being able to perform a breakdown on the fly.

All I need to do to perform a breakdown is to supply the function with the full dataset and specify which keys to look at to start building categories. The order of the breakdown is important and determines the structure of the tree that is generated as a result.

For example, let's say I want to look at party affiliation. Then for each party I want to know what are the positions held by those candidates. Then for each of those jobs I want to see which states have an affiliation.
That can be done by specifying the breakdown array as follows:

The way this code works is that it continually slices off a category index to look for in the dataset. Then it loops through the passed rows and puts them into groups based on their values for the index. These newly categorized values (which are stored in the $to_add array) need to be again gone through for the next breakdown (if there is one) and so are passed along to the next iteration so the next breakdown can be checked. The remaining breakdown list, the unchecked values that were just added, and the $data object containing the result are all passed back into the method as a recursive call.

When there are no more rows to be added and subsequently checked, the recursive call stops being made and the resulting $data object is returned to the original calling function.

Unfortunately this call can be expensive when many rows and categories are being parsed. If you have 'n' rows and 'm' columns to review so the big O(n) notation and where k is the number of distinct entries for each category is something like O(n) = n+k^m.

Tuesday, April 12, 2016

While D3 makes it easy to get started adding interesting visualizations to your web application and there are a lot of great examples on https://github.com/mbostock/d3/wiki/Gallery. The problem is that almost none of these examples are ready for prime-time without some serious tweaking. Either they need to be converted from using static data to relying on AJAX calls, or more importantly they do not support updates.

One suggestion is to use the excellent http://nvd3.org/ library by individuals who have taken the time to address these issues and provide a product that is production ready.

Another change you may need is to provide some kind of indication to the user while data is being loaded into the visualization.

Preparing for adding a loader - CSS code

First you will need to prepare an image to be used as your loading image. One with a transparent background would likely work best.

In your style.css or whatever you are using for your style-sheet, place the following code that specifies the positioning of the loading image and opacity D3 svg container. Also, you'll probably want to specify a minimum size of the container that will hold the D3 chart so the loading image knows where to position itself.

/* It is best to size your chart so the loader always knows where to display */ /* An id specifier '#' was used here */ #performance_chart { min-width: 400px; min-height: 300px; }

Add the Loading Image to the HTML code

Now you will need to add the 'ajax_loading' class to the HTML DIV that will contain the D3 visualization. Within that DIV you will add the image.

<div id="performance_chart" class="ajax_loading"> <img src="img/ajax-loader.gif"/> </div>This will display the loading image by default and also show a nice dimming effect on any svg objects contained in the target DIV.

The image I used has an opaque background, so it only looks right if you are dimming the DIV as we are doing here. Otherwise you may want to use one with a transparent background.

Loading Image

Add Javascript Code to Control the Loading Image

You'll need to activate and deactivate the loading image from whatever code you are using to call and load the data. In my case, before every AJAX call I display the loader and once the data is received I hide the loader using the following code.

Sunday, January 17, 2016

Ionic and Angular are great frameworks for building single page web apps. If you want to create an app that you can then deploy on almost any mobile device out there based on HTML5 and Javascript (JS), then you are starting in a good place.

If you are just building an app that does not communicate to other websites and deals only with information stored locally or already on the app, then you will have no issues. What the guides do not explain well is all the issues you will have communicating with other websites. These are JS features (or limitations) that protect users from malicious js code. Native Android (dalvik) and iOS (Objective-C/Swift) apps do not have that limitations, so native developers may be unfamiliar with these restrictions.

Make sure your server allows remote access by Javascript:

If you are communicating to another server, you will need to set it up to allow for Cross-Origin Resouce Shared (CORS) access or JS will not be able to read the responses. If the server you want to talk to is not your own and does not have Access-Control-Allow-Origin in its response headers set to where you need it (generally '*' or 'file://'), then you'll need to find a different way such as a proxy or a native app.
In Apache's httpd.conf file, you will need something like this on the directory you want to allow access to:

<Directory "/your_www_dir"> #You may prefer "file://" instead of "*" because it is more restrictive Header set Access-Control-Allow-Origin "*" ...

Configure the app's config.xml file to allow access to outside sites (i.e. beyond 'file://'), add after <content src="index.html"/>. Add the last two lines to allow Android/iOS apps to open sites other than you own (if desired):

Load your code or try the sample project:

The sample project uses the Angular $http service to communicate to a sample website. I use http://espn.go.com as an example because they send an Access-Control-Allow-Origin = '*' and allows us to test our app. You can see the response in the Message section and any errors in the Error section.

iOS app publishing tips

Something you should never ever do - have Allow Origin set to * and Allow Credentials to true

According to the spec you can't have Allow Origin = "*" and Allow Credentials set to "true". There is a really good reason for this. It prevents malicious Javascript from using your credentials saved in cookies against you. Say you logged into a website and it knows who you are through a cookie. If in another window you ran some malicious JS code and both of these settings were enabled, the JS code could look like a logged in user to the remote server. Not so bad if it is a sports website, but horrendous if it is your banking site. With all that said there is a way to do this in Apache. Just echo the given origin back to the user. The browser never sees it as Allow Origin=* so it allows the request.

The manual for Ionic makes it seem so easy to get started - and it generally is... that is until you go to publish your app to the Apple store and run on real devices. It can be hard getting started if you don't know you need any of these crucial elements. Later versions of Ionic already include some of these steps making future builds easier. Here is a list of some solutions to pitfalls I've run across publishing Ionic apps to the Apple App Store.

Make sure you have your provisioning license

In using iOS, you'll need to create an AppId and with it an associated provisioning license at developer.apple.com. This needs to match the widget id in the Ionic config.xml.

Create and Set the widget id for a provisioning license developer.apple.com, then update config.xml:

<widget id="com.company_name.app_name" version="x.x.x" ...

Make sure the system can find your provisioning license

In my system it initially was not able to find the license. So, I needed to perform this step in order to properly deploy

$ sudo cp -r ~/Library/MobileDevice/ /Library/

If this is not set correctly, you can get the following error when deploying your app to a device:

When accessing non-HTTPS endpoints, check your App Transport Security

When you perform ionic build ios, a
platforms/ios/{app_name}/{app_name}-Info.plist file is created. If your
app ONLY accesses HTTPS, you won't need to set this. Otherwise add the
bolded lines to the file:

Building your app in Xcode

In order to send your app to the Apple App Store, you will need to load your app in Xcode. When you perform ionic build ios it creates a file in your platforms/ios/{app_name}.xcodeproj file that you open in Xcode.

In my version of the project I needed to make some modifications to the project in order to build. Under Build Settings / Search Paths / Header Search Paths, I added:$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include
To both Debug & Release for Any SDK.

Select the correct orientation and display settings

Under General / Deployment Info, Select Add device Orientations. Do not select a Main Interface - this should be left blank. Make sure you have selected all desired orientations and 'Requires full screen'. It will put these keys in the plist file, although that does not seem to be the only location they are required because setting these without doing so in Xcode does not set the values properly.

Setup the custom icons for the app

Set your icon & splash screen in the resources folder. Use a minimum of 192x192 for the icon and 2208x2208 for the splash screen (it will be cropped for portrait/landscape). Run ionic resources to automatically compile the icons into your project so it will appear on the device:

Export the app from Xcode and upload the app to the Apple App Store

Initially the Project / Archive will not be available. Next to triangle play button and the square stop button, the current device your can deploy to is selected. Click the area to change this from iPhone to Generic iOS device. It does not look like an input combo box, but you can click on it to change it.

Click here to change the deploy target and activate the Archive selection under the Product menu

You'll need to export the project to an archive to publish to iTunes
connect and then run have processed through the app store. Open Xcode. Select Project / Archive from the Xcode menu.

Thursday, January 15, 2015

Apache Forbidden Access Issues

Linking files to Apache on a new install of Cent OS 7 with Apache 2.4 was not quite as smooth as I imagined.

The Setup

I'm working a new server and I want to link to another location so I can use Dropbox to work on files locally and have them automatically updated to my development system. Since it is easiest to install in the root directory, the Dropbox files automatically get setup in the root user's home directory. That is not a good place to link the document root to in Apache. The most logical thing to do was to copy those files out to another better location where they can be served by Apache. These files were still owned by root and I didn't want to change that, so I creating a symlink to get it to work.

As root (note: my document root was /var/html)

cd /var/html ln -s /usr/demo/html/ demo

When trying to run in Apache, I would still get the Forbidden error message.

NOTE: When Apache follows symlinks, the path must be accessible all the way down by the calling user (this means you need execute access in the folder you are linking and the parent folders above it). To make sure this folder is accessible by others, I would use the following command:chmod o+x /usr /usr/demo /usr/demo/html

That didn't work for me, but it should work. I just didn't realize the underlying problem I was experiencing which I will get to in a minute. So now, I'm thinking I'll try to use an alias and edited and saved the new config file.

Opening Apache config, I edited it as follows:sudo nano /etc/httpd/conf/httpd.conf

Alias /demo /usr/demo/html

<Directory "/usr/demo/html"> Options FollowSymLinks AllowOverride None Order allow,deny allow from all</Directory>All the online literature was pointing me in this direction.Since I am using the new CentOS7 I need to restart the service using the system control program.

The server restarted properly but I am still not able to access the page and still the Forbidden error pops up in my browser. Looking in the /var/log/httpd/error_log was somewhat helpful:[Thu Jan 15 14:37:07.549412 2015] [authz_core:error] [pid 30582] [client x.x.x.x:yyyy] AH01630: client denied by server configuration: /usr/demo/html/test.phpThis was telling me that I didn't have a linux permission error accessing the file, but that I had an Apache configuration file error. Back into the httpd.conf file.

The Solution

After a little digging, I found that Apache 2.4 (that I had on the new server) handles permissions differently that the previous version 2.2 that I was used to using.Finally modifying my httpd.conf file resulted in:Alias /demo /usr/demo/html

<Directory "/usr/demo/html"> Options FollowSymLinks AllowOverride None Require all granted</Directory>Now everything works. I just hadn't been aware that setting aliases in new Apache 2.4 installtion requires a couple changes in the httpd.conf file to get things working properly. All this time it was just I was using: