Wednesday, November 28, 2012

Stealing Android Apps

Lifehacker is promoting an app that allows users to remove ads from their apps.  In my book, it sure feels like stealing.

A few years ago a similar situation played out on our desktops.  Villainous spammers made internet browsing a clicking war as they used pop-up windows to shove their ads in our faces.  In response, browsers mercifully designed pop-up blockers that has all but stopped the madness of popup ads. 

So, what is different about the situation?  I don't think there is anything different.  The only difference for me is that I'm the guy being blocked this time. I guess it's one of those, sucks to be me situations.

So, what can be done?  Are we in a hopeless predicament?

I know that Android Apps can include an end user license agreement (EULA).  Making users agree to a legal document makes me feel a bit dirty.  I want to make my users feel good when they use my product.  I can't imagine that this would alleviate the situation either.  

Maybe the solution is just to educate our clients.  Here's a letter I could send: 

Dear Android User,
I'm glad you downloaded and installed my app. I genuinely hope you enjoy using it, and I hope it makes your life easier and happier.  But you should know something.  As much as I like building applications, writing code is hard and time consuming.  It's difficult to put together an Android app that works well on tiny phones running Honeycomb as well as a tablet running Jellybean.  Now, don't get me wrong, I'm happy to work through the bugs and create something awesome for you.  With that said, can you please allow my small pop-up to be shown in the app you downloaded from me.  Better yet, if you see something of interest, please feel free to click on that ad.  It might be a little annoying to you, but each of those clicks and views mean a lot to me.  And if you block those ads, well, it stops my income flow.  That means, no money to pay for power, no power for computer to run, and no more development of basically free apps for you.  So let's work together on this one. 
Sincerely,
A working for pennies - android app developer. 

PS. If you really *hate* ads, feel free to email me or leave a comment telling me how much you'd like to pay for an-ad free version. 

I'm not sure if that would work either.  I really think Google should step up to the plate and help us small app developers out.  Either, ad blocking apps should be removed from the play store or they should help us block the blockers!

So, what do you think? Is it stealing? Is there a better existence we could all mutually agree to?

Monday, November 26, 2012

Another Android Chart

This post is part of series about building a simple Android App.
If you haven't done so yet, read an overview of these posts here.

Never design what you can steal - Jeff Atwood.

In the dual pursuit of building a pretty Android app and increasing my Android development skills, I created my own "view" which displayed a custom drawn pie chart.  Overall, it was a great success.  But after going through the process of designing a custom view (for a rather standard shape) once, I thought it would be good to 'steal' something that works right out of the box.  Or in other words, "good programmers code, great re-use" - not sure where that's from.

There's an app, I mean a library, for that
I thought it would be nice to add a line chart to my Android app.  After some research, I ended up working with charting library called achartengine a try.  Here are my notes on what transpired.

AchartEngine tutorial with eclipse
1. Set up the library.
- Download it.
- Unzip the file and find the file achartenginedemo/lib/achartengine-1.0.0.jar .
- Copy that file into your <your_project_name>/libs
- Open your workspace/project in eclipse.
- If you don't see the file under the libs directory, right click on the folder and choose refresh.
- Right click on the achartengine jar file, go to 'Build Path', go to 'Add to Build Path'. You should see the achartengine jar file under the Referenced Libraries section now.

2. Create a class that will create the chart intent.
Here's my code for it.
public class ALineChart 
{
    public Intent getIntent( Context context )
    {
        int[] x = { 1 , 2, 3, 7};
        int[] y = { 2, 4, 16, 64};
  
        TimeSeries series = new TimeSeries("Line 1");
        for ( int i = 0; i < x.length; i++ )
        {
            series.add( x[i], y[i] );
        }
  
        XYMultipleSeriesDataset dataset = 
            new XYMultipleSeriesDataset();
        dataset.addSeries(series);
  
        XYSeriesRenderer renderer = new XYSeriesRenderer();
        renderer.setPointStyle( PointStyle.CIRCLE );
        renderer.setFillPoints( true );
        
        XYMultipleSeriesRenderer mrenderer = new 
            XYMultipleSeriesRenderer();
        mrenderer.addSeriesRenderer(renderer);
        
        Intent intent = ChartFactory.getLineChartIntent( 
            context, dataset,mrenderer, "My first line" );
        return intent;
    }
}

3.  Create the object to make the chart intent.
I added this from a fragment, but it could be called from an activity.
public void some_event_handler()
{
    ALineChart aChart = new ALineChart();
    Intent aChartIntent = aChart.getIntent( 
        getActivity().getApplicationContext() );    
    startActivity( aChartIntent );
}
That is just a simple example with some toy data.  I may update later if I find some interesting gotcha's or figure out how to make this all work better.

Update: After some struggling, I found a clip on Youtube that really explained this process much better than I could.  If the link doesn't work, just search for achartengine.  I subsequently updated my tutorial to fall in line with what I saw on youtube

I got a custom domain name

So, after I bought my custom domain name, I was able to retire my blogspot address.  I'm still not sure if the expense of paying for a custom domain name was worth it. Although the cost is pretty small, so I think there isn't much to lose.

On my home computer, I tried searching for 'refactoring project' and this site was the fifth item listed.  Of course, the phrase 'refactoring project' is not exactly a well known catchphrase, so this might be an honor that no one else is really shooting for.  Nevertheless, it's encouraging to know that my domain name is unique enough that you can actually find it without being lost in a forest of other similarly named sites.

However, I realized that searching on Google is not a deterministic event.  Google search results are different depending on who is searching.  So, when I reported above that my blog was the 5th result when searching for 'refactoring project', that was true.  However, when I searched again on another public computer, my site was not even on the first page (or second or third ... ).  So it seems that I have a lot to work towards. 

Sunday, November 25, 2012

Ping Pong Playa

I was browsing through Netflix last night, and I came across Ping Pong Playain the Feel Good section and decided to give it a try.

The premise of the film is about an immature Chinese American, who is wasting away his life playing video games, but finally does good when he trains to win a ping pong tournament for his family.

It is similar to a movie like Napoleon Dynamite, because its protagonist is incredibly awkward.  It is similar to any sports movie as it has an initial defeat, a training video montage and a final battle.

I think it does a good job of showing the immigrant family experience.  The parents of the protaganist alternate between English and Chinese in a way that felt very authentic to me.

There is definitely a racial component to this movie, but there's not much to comment on.  It is just one of the drivers of the movie. Much like Chris Farley's weight was used for comedic purposes, so were the racial factors in the movie.

Should you watch this movie?  Maybe, if you are looking to kill some time and don't want to think.

Saturday, November 24, 2012

My Blog List

Blogger has a widget called 'Blog List' which is a list of blogs that you endorse.  I like this idea in priciple.  If you like this blog, maybe you would like to read what I like to read.  So, there's a list.

But I wanted to also note why I like a certain blog so that you'd have some reference as to why I think it's good and how it influences me.  So this post, which I will add to over time is my annotated blog list.

Scripting News by Dave Winer.
This is the model I use for my blog.  Dave covers a wide range of topics from the techie tools he likes, the software he hates and loves, politics, basketball, movies and biking in New York City (to name a few).  I think most people recommend blogging about a single topic, but he doesn't follow that rule - and neither does my blog. 

Coding Horror by Jeff Atwood.
This is a blog from one of the founders of Stack Overflow.  In his words, this blog is about  "programming and human factors".  I find his posts to be well researched, easy to read and humorous.  Moreover, maybe it's just me, but I always find his posts to be challenging.  He challenges the reader to think harder and do better.  There was a series of posts a while ago about building a poker bot, and he said something to the effect that any decent programmer could build ones of these.  Is that true? I'm not sure, but I definitely felt challenged to think about it and see if I could do it or not. 

Blog Maverick by Marc Cuban.
Marc Cuban is very rich and owns the Dallas Mavericks basketball team.  He's an entrepreneur who writes mostly about business, technology, and politics. His posts typically argue some point, with a decent amount of depth: read - some of his posts can be pretty long.  However, he doesn't post very often, which balances things out.  I always find his posts to be thoughtful, and he's interested in alot of the same subjects I am peripherally interested in.

LifeHacker.
In contrast to most of my other blogs, lifehacker is more of a site with a feed that I subscribe to.  This site gives tips on how to be more productive in life.  There are tons of posts that I just skip over but there are often a few times a week where I will read through the post and learn something new.  For example, lifehacker taught me about the world of Do It Yourself robots like the arduino, and I started building one which might be the subject of a blog post later on.

Passive Income by Pat.
This blog provides articles on internet businesses.  He details with incredible transparency how much he makes, what works, and what doesn't.  This blog will inspire you and make you feel like a free-lance internet based job is actually possible.

More to come ...

Friday, November 23, 2012

Knicks lose to the Rockets

Tonight, the New York Knicks were blown out by the Houston Rockets.

We can chalk up the loss to the Knicks being on the end of a tiring road trip, or Chandler Parsons having a well-above average performance, or we could overreact and say that the Knicks are a doomed team going nowhere.  Maybe it is a combination of the three.

A microcosm of the Knicks unraveling came in the third quarter.  After Carmelo Anthony missed an ill-advised one-on-one shot, he began complaining to the ref that he was fouled.  Unfortunately, the ref was standing on the sideline, causing Carmelo to turn away from the basket, while a Rocket ran right by his back and had a free dunk.


Soon after, Tyson Chandler got tangled up with Omar Asik, and Chandler threw an elbow at Asik, eliciting a flagrant foul.  At this point in the game, Chandler was getting out-rebounded, out-played, out-hustled, out-manned, out-witted ... (you get the point) ... by Omar Asik.  So much for veteran leadership. 

I guess these are just moments of frustration, and we'll see how the rest of the season plays out.  But the one person I kept my eye on was Coach Mike Woodson.  Would he yell at his guys? Was he also piping mad and berating the refs?


As far as I could tell, he had the same emotionless face he typically has for the better part of any game.  Maybe he doesn't want to yell at his guys in front of the media and he's gonna rip into the guys later.  Maybe this is a player's league, and he doesn't want to get the boot like the previous Mike, coach Mike D'antoni.  Maybe he gave on the night.

Maybe the solution is to end the road trip, have a day off, and play against the lowly Pistons.

Affiliate Ads in this blog

Adding ads
In November of 2012, I began adding Google Affiliate ads in some blog entries.  However, I have since moved to using the amazon associates program for affiliate ads. 

I never felt like I understood exactly how Google's affiliate program worked.  For example, Google Affiliate Ads is supposed to work in this fashion: "When a blog visitor clicks your affiliate ad and makes a purchase, you may earn a commission for referring that visitor."  Why does the "may earn a commission" clause mean?  What instances would a commission be denied? 

I also found that the universe of possible products that I would like to endorse was not covered by Google's affiliate ads.  If I did find a product I would like to endorse, it was often selling at a higher price.  Using Amazon solves these issues.  I can endorse almost anything, and the price is always competitive. 

Of course, the proof is always in the sales numbers.  I will make (very happy) updates if there is ever any progress on that front.

Contrived emotions

I'm watching American Idol with my wife.  More accurately, my wife is watching American Idol and preventing me from watching basketball.  For my wife's sake and ultimately mine as well, I'll voice my complaints with the show in this blog post, instead of to her. 

Today is the Thanksgiving episode, so each singer or group is dedicating their performance to someone they are thankful towards.  And boy oh boy, are they laying it on thick.  We've had dedications to a single mom, a dad who gave up his dream of music, a long-lost sister, youth mentors, and the big cheese himself - GOD. 

I know that giving these singers a back story is important for viewers to feel connected, but I wish they would just focus on the product of the show - singing performances, instead of forcing these contrived stories onto us.
But, if others like the show the way it is, as evidenced by the millions of viewers (including my significant other), I guess I'm better off complaining in relative silence on this blog.

My cleaning style = my coding style

The family came over for thanksgiving yesterday, which meant I had to clean.
As I was cleaning, I found myself using my own 80% rule.  The rule is to do about eighty percent of the job and then move on.  So, if you're dusting, do most surfaces, but don't worry about the little crevices behind the lamp in the farthest corner of your bedroom or reaching behind the the television.  After you do eighty percent of a job, move onto the next one, be it dishes or sweeping or whatever.

If you finish all of the jobs, or 80 percent of your job list, you can go back through your list and do 80% of what's left, and so on and so on ... While things don't end up perfectly, after every passing iteration, the job percent completed goes from 80 to 96 to 99.2 to 99.84 ...

This is basically the same strategy I use when I'm coding.  Although you always want to cover the corner cases so that you're program or api works well and feels professionally polished, it's often a better practice to get 80 percent of the job done.  If your clients notice the missing 20 percent, or maybe the word is "when", then you can go back to the drawing board then.

Luckily, there's another rule of nature, the 80/20 rule, which says that 80 percent of any effect is caused by 20 percent of any cause.  So, if I clean up 20 percent of what feels messy, then that'll end up doing 80 percent of the job.  Combine this with my rule and I really don't have to do any work at all!



Disclaimer: I'm sure there are cases where this doesn't apply, but I'll just throw in one more cliche and say that it's just a rule of thumb.

Tuesday, November 20, 2012

Daily tools - podcast manager

Lifehacker has a series where they interview a productive person and ask them how they work, live and play.  These people are always very accomplished and their ways of doing work seem very polished.  I wonder how many iterations these people went through before finding the tools and methods that worked for them...

In any case I thought I'd note one of my most used tools and how I use it, the BeyodPod podcast player. I use the free version of this App which is installed on my Android smartphone.  I am subscribed to a few podcasts and I've tried countless others.  For now, I am listening to a podcast on general sports discussion, NBA basketball, coding, and Korean language lessons. I listen whenever I am walking - which is quite a lot for me in New York City. I walk my dog a couple of times a day and I walk to and from work. I basically listen to a podcast whenever I have some down time.  This way, even those small moments that are othewise wastes of time, like waiting in line, can be somewhat productive and/or entertaining.

Beyondpod is definitely the best podcast player I could find for android.  I am leaning towards buying the paid version - which gives me a few nice features like automatic updating.  

With that said, I remember iTunes being a better podcast manager when I had an iPhone. It seemed easier to get update for my subscriptions.  Also I was able to listen to podcasts at 1.5x speed - a real time saver, without having to buy and install a separate app.

Monday, November 19, 2012

Knicks had a moral victory last night

The other night, the Memphis grizzlies scored more points than the our new York Knicks.  Thus, the Knicks were defeated.  However, here were the moral victories:

Rasheed Wallace can abuse people in the post. 

Amare Stademire was missed, in principle.  The Knicks were killed on the boards by our old teammate Zach Randolph. Could Amare have helped? Not sure. But at least we have a desperate need that he could fill in theory.
 
JR Smith had a bad game. He was in the middle of a minor scuffle and his shot was not falling.  Everything was a struggle.  Yet, he didn't melt down.  Maybe he is more mature this year.

Jason Kidd is impressive.  He's a great spot up shooter, has quick hands and makes good decisions. 

Carmelo Anthony also had a rough night with fouls, but he stayed very aggressive.

Progress Report

So here are some highlights from the last year with regard to my Android development experience.

How I ended up with an Android Phone.
About 11 months ago, the day after Christmas 2011, I got my first smart phone, the iPhone.  In April of 2012, my mom needed a smart phone, so I gave her my iPhone and borrowed an old Motaola Droid from my wife.  A few weeks later, my wife lost her phone (actually it was stolen), so I gave her the droid back and I ended up buying a new Samsung Galaxy Nexus for myself. Except for the fact that the price of the phone dropped by about $100 after a month of ownership, I have been very satisfied with this phone.

3 months to write an app.
In July of 2012, I decided that I'd try to write my own Android App.  Three short months later, I published my first app to Google Play.  The App Usage Monitor app that I published is incredibly simple, but I think a turnaround time from thinking about an app to publishing one is pretty good, given that I had never written Java before!

Not - In the money.
It's now late November, and there has now been 20 user installs, with 10 active user devices.  I haven't solicited any of my friends or family to use my app, so these are all unbiased downloads and installs.  Monetarily, there hasn't been much of a windfall.  I have earned $1.98 in revenue from AdMob.  In comparison, I've earned 47 cents from Adsense revenue linked from this blog, so I haven't really realized any financial benefit for my effort in this app or in this blog.

Was it worth it?
I judge this experience as a complete success.  I developed an app that I like to use.  I learned about a new development and deployment process - eclipse, git, Google Play store.  I got to write some Java code.  I had a lot to blog about.

Basically, I was creative and produced something.  This, for me, is one of the most satisfying ways to spend your time.  While consuming content (watching television, reading blogs, or listening to podcasts) is fun and enjoyable, it is much more fulfilling to struggle and create something, even if your audience is incredibly small.

The future
I think the app that I developed has all of the central components that I envisioned for it.  Nevertheless, I have a few updates that I'd like to make to my app.  These include adding another view that will make it easy to visualize data, making my app more tablet friendly, and providing better ways for a user to save their data.  I think these are minor updates that shouldn't take me too long.  After these features are implemented, I think I will begin working on a separate app.  I plan to work on a very different type of app so that I can learn how other apps function. 

Finally, in a somewhat related note, I think I will get a Nexus 7 for Christmas.  It will make development on tablets easier and I hope it will open my eyes on new  tablet friendly apps that I can develop.  Also, it's just cool and I want one.

Wednesday, November 14, 2012

Android sqlite database questions

Android apps can easily use sqlite databases for data storage. Here are a few questions and answers about sqlite databases on android accessed via the SQLiteOpenHelper class.

1. What happens to the database associated with a given app, when the app is uninstalled?
If you create the table using internal storage, the database is wiped out. 
If you created the table on external storage, the data is preserved.  
- Another way to clear out a database is to go to Settings --> Apps --> Go to an App, and then click "Clear data".

2. How do you make changes to a database, like adding columns or an index?
In your class you should declare a variable for the version number like:
private static final int DATABASE_VERSION = 1;
When you want to make an update, change the database version to 2.
You will also need to override the onUpgrade function like this:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
{
// Depending on whether an old version existed
// and what version you are going to,
// you can customize what tables should be
// added, deleted or modified.
if ( oldVersion == 1 && newVersion == 2 )
{
// Do something.
}

// Call your onCreate function if you want ...
onCreate(db);
}
While this may seem obvious, I don't think you can 'downgrade' your database version number. At least for me this caused my app to crash.

Also, if you call another function from onUpgrade or onCreate, make sure to pass the 'SQLiteDatabase db' argument to that function as well.  Creating another db reference will cause errors.

More questions to come if I ever learn anything else ...

Saturday, November 3, 2012

Android App Updates

A couple of thoughts/questions about best practices for rolling out android app changes.

1. Is there a way to publish a new version of an app, but have it released or activated for only a limited set of users?  Or just for me at most?
One way to test a new version is to circumvent the Google Play store.  You can distribute your apk to testers any way you like and then you can use an app like Airdroid to install new versions of your app.  This is especially useful if you want to test how upgrades rather than clean installs. 

2. How often should I push out updates? 
It'd be coolest for me to push out frequent incremental changes.  This is better for testing and backing out changes if needed.
However, I don't want to annoy my users with constant updates. 

3. Do most android users set automatic updates to be on for their apps? How can I find out whether my users have turned this feature on?
I'm open to any suggestions. I wonder if Google collects such stats ...

more questions to come ...

Thursday, November 1, 2012

Google reader

I am a big fan of Google Reader.  With that said, I've been using it for about a year now, and that's just enough time for me to begin complaining about it.  

Duplicates.
Some feeds suffer from duplicate posts.  It would be nice if Google Reader could skip articles where the title and text are exactly the same.  I imagine that these are appearing because the meta-data is different or the feed provider made a duplicate post, but as a reader, this is pollution.

Articles, videos, podcasts ...
I wish there was a way to filter out non-text based articles that are basically links to a video or audio link.  I suppose some people want to see these, but I generally don't want to.  I imagine this is difficult to do, because just about any article could have links to external links.  Maybe there should be a filter that excludes any 'article' that has less than 200 words or something like that?

Pointers ...
Similar to the gripe above, some feeds contain only a title and a snippet of the article.  I wish Google Reader could capture the whole article to save me from having to click into the article and then requiring multiple clicks to get out of the article.