My First Visual Studio Extension


Recently one of my friends on twitter mentioned they were looking for a Visual Studio extension that would keep the cursor a few lines away from the edge of the editor window to allow you to preview the upcoming text when using the arrows to move the cursor. After looking for one myself and not being able to find one, I decided to take a shot at creating an extension to do just that. It seemed like something that would be pretty easy to make. So I downloaded the Visual Studio SDK and got started. A few hours later I had the basic functionality down and sent it off to my friend to see if that was what he was looking for.

After hearing back that it was what he was looking for, he encouraged me to publish it to the Visual Studio Extension Library, which I did. The extension is called Padded Cursor. If you have VS 2010, please download it and let me know what you think of it.

author: John Nastase | posted @ Sunday, January 22, 2012 5:44 PM | Feedback (1)

Custom Android ListActivity


In a previous post I demonstrated the concept of “master pages” in Android. Essentially what this did was allow you to have a base layout so that you didn’t have to repeat the same layout on all views that had the same things at the top and bottom of the layout. In the comments someone asked how this could be applied to the ListActivity. I haven’t done much with Android the last few months and have not had the chance to use this activity type yet so I decided to look into it.

After throwing some simple pages together I am not sure the master page concept can be directly applied to this situation. The reason being is that any class the extends the ListActivity class needs to have a ListView with the id @android:id/list. If we want to have a base layout with items above and below then we don’t want to have the list in that view.

The alternative is to create a ListActivity with a customize layout. Looking at the documentation the requirements are very simple. As mentioned earlier your layout must include a ListView with an id of @android:id/list. Then in the onCreate you call setContentView and pass in the id of your layout. See below.

Here is the layout for my activity:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   3:     android:layout_width="wrap_content" android:layout_height="fill_parent"
   4:     android:orientation="vertical">
   5:     <ListView android:id="@android:id/list" android:layout_width="wrap_content"
   6:         android:layout_height="wrap_content" android:layout_weight="1" />
   7:     <LinearLayout android:orientation="horizontal"
   8:         android:layout_width="wrap_content" android:layout_height="wrap_content">
   9:         <Button android:layout_width="wrap_content" android:id="@+id/button1"
  10:             android:layout_height="wrap_content" android:text="Press Me" />
  11:         <Button android:layout_width="wrap_content" android:id="@+id/button2"
  12:             android:layout_height="wrap_content" android:text="Press Me" />
  13:     </LinearLayout>
  14: </LinearLayout>

And here is the activity.

   1: public class MyListView extends ListActivity {
   2:  
   3:     Button button1, button2;
   4:  
   5:     @Override
   6:     protected void onCreate(Bundle savedInstanceState) {
   7:         super.onCreate(savedInstanceState);
   8:  
   9:         setContentView(R.layout.my_list_layout);
  10:  
  11:         button1 = (Button) findViewById(R.id.button1);
  12:         button2 = (Button) findViewById(R.id.button2);
  13:         
  14:         button1.setOnClickListener(button1Listener);
  15:         button2.setOnClickListener(button2Listener);
  16:  
  17:         String[] names = new String[] { "Item1", "Item2", "Item3", "Item4",
  18:                 "Item5", "Item6", "Item7", "Item8" };
  19:         this.setListAdapter(new ArrayAdapter<String>(this,
  20:                 android.R.layout.simple_list_item_1, names));
  21:     }
  22:  
  23:     private OnClickListener button1Listener = new OnClickListener() {
  24:  
  25:         public void onClick(View v) {
  26:             String[] names = new String[] { "Item1", "Item2", "Item3", "Item4",
  27:                     "Item5", "Item6", "Item7", "Item8" };
  28:             setListAdapter(new ArrayAdapter<String>(getBaseContext(),
  29:                     android.R.layout.simple_list_item_1, names));
  30:         }
  31:     };
  32:  
  33:     private OnClickListener button2Listener = new OnClickListener() {
  34:  
  35:         public void onClick(View v) {
  36:             String[] names = new String[] { "Blah1", "Blah2", "Blah3", "Blah4",
  37:                     "Blah5", "Blah6", "Blah7", "Blah8" };
  38:             setListAdapter(new ArrayAdapter<String>(getBaseContext(),
  39:                     android.R.layout.simple_list_item_1, names));
  40:         }
  41:     };
  42:  
  43: }

I added some buttons to show you how to change the items in the list by clicking one or the other. Obviously you would want to get your data from a data store of something other than a static list. As always I hope this helps and if anyone comes up with a way to have a base activity and layout I would be very interested in how you accomplished that. Here is the Android documentation for some more info.

http://developer.android.com/reference/android/app/ListActivity.html

author: John Nastase | posted @ Monday, August 08, 2011 11:45 PM | Feedback (0)

Capped Internet Usage - Few Winners, Many Losers


Earlier this week AT&T became the second major ISP (Internet Service Provider) to start capping the usage of its customers. The cap currently stands at 250 gigabytes per month and users will be charged for each additional 50 gigabytes they go over. Comcast also caps it usage at 250 gigs but instead of allowing you to pay for more they just boot you off their service after your second violation, at least that’s what their FAQ page said. I disagree with their decisions in so many ways I almost don’t know where to begin. I suppose I will start with a quote from the article I found on CNN.com about the recent AT&T cap, link at end of this post.

"Our approach is based on customers' feedback," said Mark Siegel, spokesman for AT&T. "They told us that the people who use the most should pay more, and they also told us we should make it easy for them to track their usage. We think our approach addresses these concerns."

I have a few problems with this statement. First, I find it hard to believe that most of their customers would ask for less and continue paying the same rate. Why would I want to go from getting unlimited usage for some monthly fee to getting capped after a certain amount for the same monthly fee? Maybe users did ask to be able to keep track of their usage but how does that translate into putting a cap on that usage? The second issue I have with this statement is about users who use the most bandwidth should pay for it. As far as I ‘m concerned they do already. I went to AT&T site to see some of their offerings and they have several internet plans with different speeds. By selecting a faster, more expensive plan aren’t you in effect paying to use more than someone who selects a slower plan? If you offer different speeds of service then shouldn’t you also have different caps in place. Why would I pay more for a faster connection if the only thing it means is that I am going to reach my cap faster?

Speaking of caps and connection speed, if you’re going to put caps in place then the speed of your connection should determine your cap rather than everyone having the same cap. I don’t have a good analogy to this but that is like giving 10 people 10 gallons of gas for their cars and saying you can only go 200 miles with what I gave you no matter the fuel economy of your car. OK, it that might not be the best analogy but hopefully you see what I am getting at. Don’t get me wrong, 250 gigabytes is a lot of data. But that is only by today’s standards. I sure most programmers know the famous, although misquoted saying from Bill Gates about 640K being more than enough memory for anyone. What happens when AT&T decides to offer even faster connections in the future? I would like to believe they will also increase their cap as they get faster but I find that hard to believe since they already offer different speeds for their service now. Also, depending on what you read, video accounts for almost half of internet traffic now. With services like Netflix, Hulu and other video offerings available this figure is only going to increase as people do more than use the Internet for more than just email and checking the news.

The capped approach also presents another issue. If you as my ISP are going to cap my usage then why don’t you block the ads that appear in my browser? Since I am now paying based on my usage I don’t want ads counting toward my cap. Take your favorite search engine, if you search for anything the first few links returned are ads along with the last few. In addition there are also adds to the right of the results. Then once you find the link you’re looking for there are more probably more ads on the page you are viewing. I am sure some will argue that ads don’t take up a lot of data but over time it could add up. What if you are searching for multiple topics and clicking on the whole first page of links on several searches to try and find what you are looking for? That adds up to a lot of ads and some ads even use JavaScript to update their image without you leaving the page.

Capped usage also affects the whole browsing experience and limits innovations. This directly affects me as a web developer. Let’s say I come up with what might be the next big thing on the Internet. Obviously I would start with just about zero users so I would tell some of my friends to browse to my site and check it out. What happens if most of them have capped usage? Some of them might say great but I have some movies I want to watch on Netflix and I might need the usage this month, maybe next month. Obviously that is an extreme example but it might not be so farfetched in the future. What I am trying to get at is that users may feel hesitant to try new sites. What if YouTube hadn’t come out and usage was capped. If I told to check this site where you could watch all kinds of uploaded videos you might be a little hesitant since video would potentially use up some of the cap you might need to do something later.

What about all this talk of the Cloud? As we have the need to access our data in more and more places Cloud offerings are starting to pop up from companies like Amazon and Microsoft that allow you to store you data in one place and download it as needed. With a capped Internet why would I want to take advantage of these services? Odds are, I won’t. The ISPs will probably offer the same things as these companies and be nice enough to not count that towards your usage. If that last sentence doesn’t throw up all kinds of red flags please read it again. I am sure Comcast has already said it will offer a video service like Netflix and Hulu that won’t count against your cap and I am sure AT&T will probably follow since both of these companies provide both internet and television service. This obviously puts other companies that already offer these services at a huge disadvantage and probably cause some anti-trust lawsuits to be filed.

What happens if I don’t use all of my allotted cap for the month? If I am such a burden on the network I would expect that usage to carry over. I already know the network can handle it since they will gladly charge me more if I go over my cap. Unfortunately I don’t think this is going to happen either. Even at a company such as AT&T who seems to imply from the quote at the beginning that they take customer feedback very seriously. Please note the sarcasm is the previous sentence.

As you can tell from the points above I am very upset to see that companies are trying to steer us in this direction. I feel that I have raised some valid questions that point out some of the shortcomings of capped internet usage and how some companies feel justified to charge more for less rather than take a hit on their bottom line for a quarter or two and actually improve their services. I would hope that anyone who has any services from these companies seriously consider an alternative so that other companies who are considering these business models don’t follow suit and see that as consumers, we demand more, not less. I would love to know how you feel about this so please leave me a comment below with your thoughts. Also if you feel that I have left something out or find a flaw in one of my arguments please let me know. Thanks.

http://money.cnn.com/2011/05/03/technology/att_broadband_caps/index.htm

author: John Nastase | posted @ Friday, May 06, 2011 2:37 PM | Feedback (0)

Compiled Linq Queries


For the past few months at work I have been working on importing records from one system to another. For the data access we have been using Ling to SQL. For the one system we had to perform some pretty tricky queries to make sure we got only non deleted records. To do this for all the tables we had pretty much the same query everywhere in our class, modified of course to get the different types out. When we started running the program to moves records the first thing we noticed was that it was pretty slow, and by slow I mean a record every couple seconds. Since we were processing tens of thousand of records we needed to find a way to speed this up. Our first thought was to put indexes on the database but this yielded no noticeable gain at all. We weren’t doing anything fancy in the code so I decided to do a quick Bing search for link performance tips. The search returned tons of links to blogs with 5 or 10 tips on how to improve the performance. Some of the tips didn’t seem to be relevant or feasible for our application but the one tip that I kept seeing was compiling your queries.

I had read about being able to compile your queries but never thought of it as a practical solution. Being skeptical I started to compile some of my queries and and then ran the program with and without the compiled queries. To my surprise the program run much faster with the compiled queries. Having proved that they were indeed faster I decided to replace all of my inline queries with compiled ones. After replacing all the queries we started importing records again. The performance increase was noticed immediately, we went from an average of one every two seconds to about 2 every second. I read that this could speed up performance 3-5 times which seemed to be the case here.

What is happening with compiled queries, or at least what I think is happening, is that the first time the query is run the expression tree is created and the next time it is run all it has to do is plug in the parameter(s) from the delegate. This way the expression tree only has to be created once, which is why this is great for queries that will be run over and over in your application.

 

Here are a couple links I used find this info:

http://www.sidarok.com/web/blog/content/2008/05/02/10-tips-to-improve-your-linq-to-sql-application-performance.html

http://davidhayden.com/blog/dave/archive/2008/02/19/HighPerformanceLINQToSQLCompiledQueriesORMappersEcommerceWebsites.aspx

author: John Nastase | posted @ Thursday, February 17, 2011 6:32 PM | Feedback (1)

Review of Professional Android 2 Application Development


For those of you who have been following some of my recent posts you have noticed that I have been doing quite a bit of Android development lately. Nathan suggested in the comments of one of my posts that I review the book I used to get started.

I bought the book Professional Android 2 Application Development over the summer shortly after buying an Android phone. I had tried to get started by just using the Android website, but I am not one for browsing all over a site to learn all the features of a language or platform. I wanted a book so that I would be able to learn what certain features of the platform were called and this book allowed me to do just that. The book starts with an intro and how to setup your environment to start development and then goes on to discuss views, activities, intents, menus, preferences, storage and so on. Like I mentioned, I wanted a book that would explain to mean what the features of the platform were called. By that I mean I didn’t know that the menus that show up when you long press an item are context menus or that intents are used to start one activity from another. This book did a good job of explaining exactly those things and was just what I was looking for when I purchased it.

I read the first 10 or so chapters since those contained most of the topics I was interested in and relied on the Android site and Bing for the rest of my questions. I would definitely recommend this book to anyone who has some programming experience and is looking to get started with the Android platform.

author: John Nastase | posted @ Sunday, January 09, 2011 10:08 PM | Feedback (1)

“Master Pages” in Android


The title of this post may be a little confusing because there aren’t master pages in Android. I have done a lot of development in Asp.Net which has the concept of master pages. A master page in Asp.Net allows you to put content that will be the same into the master page file and use place holders to the content that will be different for each page. The runtime then combines the master page with the requested page at runtime.

I have been working on a project for a client and the wanted their logo to be at the top of every activity. Since there were more than a couple activities I wanted have something like this master page functionality just in case they didn’t like the way it looked and wanted to change it. The solution was pretty easy. To start I created an a base Activity and derived it from the activity class. Then I overrode the onCreate and setContentView methods. In the onCreate I called the parents onCreate method and assigned any layout objects that needed to be used. In the setCotentView I created an inflater class and used it to inflate the view they passed in into a layout object on my base layout. My base layout only had a few LinearLayouts and an image for the logo. Then in my other activities I had them derived from my base Activity instead of the normal Activity class. When these activities called setContentView they were really causing their layout to be placed inside of my base layout. That was all there was to it. The only thing I noticed so far was that when requesting a progress bar (requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) this needs to be done before calling super.onCreate. I think this is because nothing can be drawn yet before calling this function. The code for my base activity and layout are below.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <LinearLayout
   3:       xmlns:android="http://schemas.android.com/apk/res/android"
   4:       android:layout_width="fill_parent"
   5:       android:layout_height="fill_parent"
   6:       android:orientation="vertical"
   7:       android:background="#000000"
   8:       android:padding="15dp" >
   9:       <LinearLayout android:orientation="horizontal" android:background="#000000"
  10:             android:layout_width="fill_parent" android:layout_height="wrap_content"
  11:             android:minHeight="50dp" android:paddingLeft="10dp">
  12:             <ImageView android:layout_width="wrap_content" android:id="@+id/ImageView01"
  13:                 android:adjustViewBounds="true" android:layout_height="wrap_content"
  14:                 android:scaleType="fitCenter" android:maxHeight="50dp" />
  15:     </LinearLayout>
  16:     <LinearLayout android:id="@+id/linBase"
  17:       android:layout_width="fill_parent"
  18:         android:layout_height="fill_parent" >
  19:     </LinearLayout>      
  20: </LinearLayout>

and the code for the activity:

   1: public class BaseActivity extends Activity {
   2:  
   3:     ImageView image;
   4:     LinearLayout linBase;
   5:     
   6:     public void onCreate(Bundle savedInstanceState) {
   7:         super.onCreate(savedInstanceState);
   8:         
   9:         super.setContentView(R.layout.base_layout);
  10:         
  11:         image = (ImageView)findViewById(R.id.ImageView01);
  12:         image.setImageResource(R.drawable.header);
  13:         
  14:         linBase = (LinearLayout)findViewById(R.id.linBase);
  15:     }
  16:     
  17:     @Override
  18:     public void setContentView(int id) {
  19:         LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  20:         inflater.inflate(id, linBase);
  21:     }
  22:         
  23: }

To use this you simply have you class derived from your base Activity

   1: public class SomeActivity extends BaseActivity {
   2:     
   3:     public void onCreate(Bundle savedInstanceState) {
   4:         super.onCreate(savedInstanceState);
   5:         
   6:         super.setContentView(R.layout.some_layout);
   7:         
   8:         //rest of code
   9:     }
  10:         
  11: }

This worked great for me and hopefully you will find this useful in your own coding.

author: John Nastase | posted @ Saturday, January 08, 2011 12:09 PM | Feedback (5)

Custom Adapter for AutoComplete


In my last post I showed how to create your own Adapter to display items how you want to in a ListView. In this post I will show you how to extend that example to allow you to set your adapter to an AutoComplete box in android. You can’t bind just any Adapter to an AutoComplete in android. In addition to deriving from the BaseAdapter class it also has to implement the Filterable interface. I thought that this would be a piece of cake and that simply extending the interface would cause some magic to happen and I would be done. Unfortunately this wasn’t the case. The interface has one method called getFilter() which simply returns an object of type Filter.

Again simple enough except that Filter is an abstract class and in order to get this to work I had to create my own Filter class. I did some research and found that the preferred approach seems to be a nested class inside of the Adapter so I went from there. I created my class and created a constructor and the stubs of the two methods we need to override from the base class.

   1: private class GameFilter extends Filter {
   2:  
   3:     public GameFilter() {
   4:         
   5:     }
   6:     
   7:     @Override
   8:     protected FilterResults performFiltering(CharSequence constraint) {
   9:  
  10:     }
  11:  
  12:     @SuppressWarnings("unchecked")
  13:     @Override
  14:     protected void publishResults(CharSequence constraint, FilterResults results) {
  15:  
  16:     }
  17:  
  18: }

After that I had to make a minor change to our Adapter class. I needed to add another ArrayList that would be responsible for keeping track of the original data and an object of our newly created class that will be returned in the getFilter method required for the interface. All that was left was to implement the methods in our Filter class. The performFilter method was easy since we simply had to look through the list and find games whose name contained the constraint parameter and and them to a temporary list. Once we were finished, we assigned this list to the values member on the FIlterResults class we were returning. Then in the publishResults method we assigned that list to our games list, which is the list the AutoComplete is binding to and notify it of the change. This method is called asynchronously from the main thread which is why it is void. Here is the complete code for the completed adapter class.

   1: public class GameAdapter extends BaseAdapter implements Filterable {
   2:  
   3:     Context _context;
   4:     ArrayList<Game> games;
   5:     
   6:     public GameAdapter(Context context, ArrayList<Game> _games) {
   7:         _context = context;
   8:         games = _games;
   9:         orig = games;
  10:         filter = new GameFilter();
  11:     }
  12:     
  13:     @Override
  14:     public int getCount() {
  15:         if (games != null)
  16:             return games.size();
  17:         else
  18:             return 0;
  19:     }
  20:  
  21:     @Override
  22:     public Object getItem(int arg0) {
  23:         return games.get(arg0);
  24:     }
  25:  
  26:     @Override
  27:     public long getItemId(int arg0) {
  28:         return games.get(arg0).getID();
  29:     }
  30:  
  31:     @Override
  32:     public View getView(int arg0, View arg1, ViewGroup arg2) {
  33:         GameView gv;
  34:         if (arg1 == null)
  35:             gv = new GameView(_context, games.get(arg0));
  36:         else {
  37:             gv = (GameView) arg1;
  38:             gv.setID(games.get(arg0).getID());
  39:             gv.setName(games.get(arg0).getName());
  40:         }
  41:         return gv;
  42:     }
  43:  
  44:     @Override
  45:     public Filter getFilter() {
  46:         return filter;
  47:     }
  48:     
  49:     private GameFilter filter;
  50:     ArrayList<Game> orig;
  51:     
  52:     private class GameFilter extends Filter {
  53:  
  54:         public GameFilter() {
  55:             
  56:         }
  57:         
  58:         @Override
  59:         protected FilterResults performFiltering(CharSequence constraint) {
  60:             FilterResults oReturn = new FilterResults();
  61:             ArrayList<Game> results = new ArrayList<Game>();
  62:             if (orig == null)
  63:                 orig = games;
  64:             
  65:             if (constraint != null)
  66:             {
  67:                 if (orig != null && orig.size() > 0) {
  68:                     for (Game g : orig) {
  69:                         if (g.getName().contains(constraint))
  70:                             results.add(g);
  71:                     }
  72:                 }
  73:                 oReturn.values = results;
  74:             }
  75:             return oReturn;
  76:         }
  77:  
  78:         @SuppressWarnings("unchecked")
  79:         @Override
  80:         protected void publishResults(CharSequence constraint, FilterResults results) {
  81:             games = (ArrayList<Game>)results.values;
  82:             notifyDataSetChanged();
  83:         }
  84:     }
  85:  
  86: }

Here is how to set the Adapter.

   1: public class ScoreKeeper extends Activity {
   2:  
   3:     ArrayList<Game> games;
   4:     AutoCompleteTextView txtGames;
   5:     GameAdapter myAdapter;
   6:     
   7:     /** Called when the activity is first created. */
   8:     @Override
   9:     public void onCreate(Bundle savedInstanceState) {
  10:         super.onCreate(savedInstanceState);
  11:         setContentView(R.layout.main);
  12:         
  13:         txtGames = (AutoCompleteTextView)findViewById(R.id.txtGames);
  14:        
  15:         games = getAllGames();
  16:  
  17:         myAdapter = new GameAdapter(this, games);
  18:         txtGames.setAdapter(myAdapter);
  19:     }
  20: }

If you run this the AutoComplete list will now look like the list from the previous example. I had hoped to be able to use the same list for both a ListView and an AutoComplete but was unable to do so. The ListView’s items would be narrowed down as I typed into the AutoComplete box. I can’t think of any way to do this of the top of my head but it would be cool to be able to use the same adapter for two different things. I would be very interested if anyone else has done this or has any ideas on how to do it. I will definitely post a follow up if I am able to do so.

author: John Nastase | posted @ Sunday, December 19, 2010 10:38 PM | Feedback (2)

Custom Android ListAdapter


This article  will explain how to make a custom adapter for a ListView used to display a list of items. For those of you not familiar with how to bind a ListView to a list of items here is a brief overview. First you need an ArrayList of a certain type and an ArrayAdapter of the same type. In the constructor of the ArrayAdapter you pass in the context, a layout id and the ArrayList of the same type and set the lists adapter to the ArayAdapter. This simply displays a list calling toString() on every item which means you have to override toString()  on your type or the objects memory reference will be displayed.

This approach is good for displaying a simple list but what if we wanted to display the name and number of a contact or just two pieces of data from the same type in each list item. For those of you familiar with Asp.Net and the GridView we could just put binding tags in our markup but that isn’t the case with Android. To start we need to make a class the extends the BaseAdapter class and override a few methods. For this example we will be displaying a list of games. We will just be displaying the game id and its name.

The first thing we need to do is create the View we will be using in the adapter. For this will we be creating a simple class that extends LinearLayout that contains two TextViews for our display. This class is very simple, it contain two TextViews with methods to set their text and a constructor that defines the layout of the items. In the constructor all we do is instantiate the TextViews and set their text. Here is the View class.

   1: public class GameView extends LinearLayout {
   2:  
   3:     TextView txtName;
   4:     TextView txtID;
   5:     
   6:     public GameView(Context context, Game game) {
   7:         super(context);
   8:         this.setOrientation(VERTICAL);
   9:         
  10:         txtName = new TextView(context);
  11:         txtID = new TextView(context);
  12:         
  13:         txtID.setText(String.valueOf(game.getID()));
  14:         txtName.setText(game.getName());
  15:         
  16:         addView(txtID, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  17:         addView(txtName, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  18:     }
  19:     
  20:     public void setID(long value) { txtID.setText(String.valueOf(value)); }
  21:     public void setName(String value) { txtName.setText(value); }
  22:  
  23: }

 

Next we need to make our class that overrides the BaseAdapter class. Here is the start of our class and the methods we need.

   1: public class GameAdapter extends BaseAdapter {
   2:     
   3:     @Override
   4:     public int getCount() {
   5:             return 0;
   6:     }
   7:  
   8:     @Override
   9:     public Object getItem(int arg0) {
  10:         return 0;
  11:     }
  12:  
  13:     @Override
  14:     public long getItemId(int arg0) {
  15:         return 0
  16:     }
  17:  
  18:     @Override
  19:     public View getView(int arg0, View arg1, ViewGroup arg2) {
  20:         
  21:     }
  22: }

 

The first thing we need to do is create a constructor. We will pass in the context and a list of games to be used by the Adapter.

   1: Context _context;
   2: ArrayList<Game> games;
   3:  
   4: public GameAdapter(Context context, ArrayList<Game> _games) {
   5:     _context = context;
   6:     games = _games;
   7: }

 

Now that we have all the data we need we just need to fill in the methods we overrode. The most important one is getView which will instantiate an instance of our custom view class and assign it the appropriate values. The other three methods are used to get the current item or count of items. Again we are doing nothing special other than creating a view and assigning its values. Here is the complete code for the Adapter class.

   1: public class GameAdapter extends BaseAdapter {
   2:  
   3:     Context _context;
   4:     ArrayList<Game> games;
   5:     
   6:     public GameAdapter(Context context, ArrayList<Game> _games) {
   7:         _context = context;
   8:         games = _games;
   9:     }
  10:     
  11:     @Override
  12:     public int getCount() {
  13:         if (games != null)
  14:             return games.size();
  15:         else
  16:             return 0;
  17:     }
  18:  
  19:     @Override
  20:     public Object getItem(int arg0) {
  21:         return games.get(arg0);
  22:     }
  23:  
  24:     @Override
  25:     public long getItemId(int arg0) {
  26:         return games.get(arg0).getID();
  27:     }
  28:  
  29:     @Override
  30:     public View getView(int arg0, View arg1, ViewGroup arg2) {
  31:         GameView gv;
  32:         if (arg1 == null)
  33:             gv = new GameView(_context, games.get(arg0));
  34:         else {
  35:             gv = (GameView) arg1;
  36:             gv.setID(games.get(arg0).getID());
  37:             gv.setName(games.get(arg0).getName());
  38:         }
  39:         return gv;
  40:     }
  41: }

 

To use this in an activity simply crate a ListView, the custom adapter and set the ListView’s adapter to our custom adapter and see the results. Here is some code to get you going.

   1: public class ScoreKeeper extends Activity {
   2:  
   3:     ArrayList<Game> games;
   4:     GameAdapter myAdapter;
   5:     
   6:     /** Called when the activity is first created. */
   7:     @Override
   8:     public void onCreate(Bundle savedInstanceState) {
   9:         super.onCreate(savedInstanceState);
  10:         setContentView(R.layout.main);
  11:  
  12:         lstGames = (ListView)findViewById(R.id.lstGames);
  13:         
  14:         games = db.getAllGames();
  15:  
  16:         myAdapter = new GameAdapter(this, games);
  17:         lstGames.setAdapter(myAdapter);
  18:     }
  19: }

 

That’s all there is to it. I know this is pretty much the android’s example minus putting creating your own ListView class but I wanted to show how to do this since it will lead into my next post on creating your own Adapter for handling AutoCompletes in android. Plus it shows you can use the default ListView rather than creating your own. Hope you will find this useful.

author: John Nastase | posted @ Sunday, December 19, 2010 10:03 PM | Feedback (10)

Intents in Android


Intents are very important to Android development. They allow you to pass data between different activities in your app and in some cases between apps. Intents were something I had trouble understanding at first but once you use them a couple times they aren’t that bad. You can use intents to start an activity that you expect to return a result or start an intent with no intention of any data being returned. They also allow you to pass data from the calling activity into the activity being started.

We’ll start by looking at how to start an intent that will launch another activity and return nothing. TO do this we simply instantiate a new intent and pass in the context and the class we will be starting. Here is some example code, this code could be inside an button click or code used by menu selections.

   1: Intent intent = new Intent(getBaseContext(), About.class);
   2: startActivity(intent);

That’s all there is to launching another activity. Please keep in mind that all activities that will be run need to be declared in the AndroidManifest file or an exception will be thrown when trying to start the activity.

Now lets look at how to start an intent that will return a value. This is very similar to the first example except this time instead on startActivity we need to call startActivityForResult which takes the intent and an integer parameter that will be used to determine which activity is returning data to the calling activity.

   1: Intent intent = new Intent(getBaseContext(), EnterValue.class);
   2: startActivityForResult(intent, 11);

Normally we would use a final (constant in .Net) variable instead of hard coding an integer value since we will need that value later. This code starts the activity. In the activity that we started, after we have done what we need to do to get the right value we need to return that to the calling activity. To do this we need to create a new intent in the activity that we started and put the data into it using the putExtra method on the intent class. After we have done that we call setResult passing in the intent to return control of the app to the original activity. Again the string key should be declared in a final variable somewhere. RESULT_OK is a constant on the activity class

   1: // this code is in the activity started by the first
   2: private OnClickListener OKClick = new OnClickListener() {
   3:     
   4:     public void onClick(View v) {
   5:         // TODO Auto-generated method stub
   6:         Intent result = new Intent();
   7:         String s = txtValue.getText().toString();
   8:         result.putExtra("com.example.helloandroid.EnteredValue", s);
   9:         setResult(RESULT_OK, result);
  10:         finish();
  11:     }
  12: };

Control is now return to the calling activity and the execution returns to the overridden onActivityResult method. It is in this method that we handle the results from the activity that returned data to us. The first thing we want to do is check the result code and from there check the request code to see which activity is returning data to us, in this case we will check for the value 11 since this is the value we passed in when we started the intent. Here is the code, notice that we use the same string value to get the string data out.

   1: @Override
   2: public void onActivityResult(int requestCode, int resultCode, Intent data) {
   3:     if (resultCode == RESULT_OK) {
   4:         switch (requestCode)
   5:         {
   6:         case (11) : {
   7:             if (data != null) {
   8:                 String s = data.getStringExtra("com.example.helloandroid.EnteredValue");
   9:                 AddNewPoint(s, (int)x, (int)y);
  10:             }
  11:             break;
  12:         }
  13:         }
  14:     }        
  15: }

That leaves us with passing data from the calling activity into the activity we are starting. To do this this we just use the putExtra method to pass in the appropriate type.

   1: Intent intent = new Intent(getBaseContext(), GameDetails.class);
   2: intent.putExtra("Game", game);
   3: startActivity(intent);

And then in the activity we started we just need to get it out. Notice the key needs to be the same  so again constants would be a good choice.

   1: @Override
   2: public void onCreate(Bundle savedInstanceState) {
   3:     super.onCreate(savedInstanceState);
   4:     setContentView(R.layout.game_view);
   5:     
   6:     // here is where we get the data we passed in
   7:     Bundle extras = getIntent().getExtras(); 
   8:     if(extras !=null) {
   9:         Game game = (Game)extras.getSerializable("Game");
  10:         if (game != null) {
  11:             //do something with the value
  12:         }
  13:     }
  14:     
  15: }

That about does it for intents. Hopefully now you have a better understanding of how to use them and like I said, once you use them they aren’t so hard to understand.

author: John Nastase | posted @ Tuesday, November 23, 2010 10:46 PM | Feedback (0)

Linq to Sql and String Truncation


For the last couple months at work we have been working on converting a customer’s clients from competitor systems to their system. Doing this involves converting the competitors database into their database. Since there are a few things that would be difficult to do just in SQL we decided to use .Net and Linq to SQL to accomplish this. Since these are mostly just little utilities to map fields from one system to the other not a lot of validation is done, other than making sure the data looks pretty much the same in both programs.  For those of you that have used Linq to SQL you know that when you drag a table onto the designer a view the fields it displays the .Net type and the corresponding SQL type. The problem we were running into involved strings and their length. What was happening was we were setting the string value but when we went to submit the changes we were getting “string or binary data would be truncated errors”.

Now if we had a small model with only a few columns this wouldn’t be so bad, but we had over 50 tables and some of those tables have quite a bit of columns in them. You would think that since the data model knows the length of the SQL field it would truncate it for you, but it doesn’t. We could also check the length of string when we set it but then there would be if statements all over the place and plus we need to log the data that is truncated for the customer to review.

What we decided to do was make a function that we could pass in a data object and loop thru all the properties and truncate and log strings where needed. What we also had to do was follow all of the navigation properties of the objects to checks their strings as well. We ended up with a recursive function to use reflection to inspect the properties of an object and its child objects if needed. If you look at the designer code for Linq to SQL you will notice that it puts a ColumnAttribute above the properties with its database type. When we looped thru the properties if we got to a string, we checked for this attribute and extracted out the length value. Then we truncated and logged the string if it was too long. For the navigation properties we loop for the AssociationAttribute. Here is the code. This was placed inside the designer file for custom code.

  1. static Stack<object> stack = new Stack<object>();
  2.  
  3.         public static void Validate(object policy, string policyNumber)
  4.         {
  5.             if (policy == null)
  6.                 return;
  7.  
  8.             //Console.WriteLine("\t{0}", policy.ToString());
  9.  
  10.             if (stack.Contains(policy))
  11.                 return;
  12.             else
  13.                 stack.Push(policy);
  14.  
  15.             foreach (PropertyInfo prop in policy.GetType().GetProperties())
  16.             {
  17.                 object[] attrs = prop.GetCustomAttributes(typeof(AssociationAttribute), true);
  18.                 if (attrs != null && attrs.Length == 1)
  19.                 {
  20.                     AssociationAttribute attr = (AssociationAttribute)attrs[0];
  21.                     if (prop.PropertyType.IsGenericType &&
  22.                         typeof(EntitySet<>).IsAssignableFrom(prop.PropertyType.GetGenericTypeDefinition()))
  23.                     {
  24.                         foreach (object item in prop.GetValue(policy, null) as IEnumerable)
  25.                         {
  26.                             if (item != null && !stack.Contains(item))
  27.                                 Validate(item, policyNumber);
  28.                         }
  29.                     }
  30.                     else
  31.                     {
  32.                         object item = prop.GetValue(policy, null);
  33.                         if (item != null && !stack.Contains(item))
  34.                             Validate(item, policyNumber);
  35.                     }
  36.                 }
  37.  
  38.                 object val = prop.GetValue(policy, null);
  39.                 if (val is string)
  40.                 {
  41.                     string value = val.ToString();
  42.                     if (string.IsNullOrEmpty(value))
  43.                         continue;
  44.  
  45.                     int maxLength = GetLengthLimit(prop.GetCustomAttributes(typeof(ColumnAttribute), true));
  46.                     if (value.Length > maxLength)
  47.                     {
  48.                         //log that we truncated the value
  49.                         LogEntry entry = new LogEntry()
  50.                         {
  51.                             Message = string.Format(@"String concantenated on policy #: {1}
  52.                                                                                     {0}In {2} on {3}
  53.                                                                                     {0}Old Value: {4}
  54.                                                                                     {0}NewValue: {5}",
  55.                                                                                     Environment.NewLine, policyNumber, policy.GetType().ToString(), prop.Name, value, value.Substring(0, maxLength))
  56.                         };
  57.                         Logger.Write(entry);
  58.  
  59.                         prop.SetValue(policy, value.Substring(0, maxLength), null);
  60.                     }
  61.                 }
  62.             }
  63.  
  64.             stack.Pop();
  65.         }
  66.  
  67.         public static int GetLengthLimit(object[] info)
  68.         {
  69.             int dblenint = 0;   // default value = we can't determine the length
  70.  
  71.             if (info != null && info.Length == 1)
  72.             {
  73.                 ColumnAttribute ca = (ColumnAttribute)info[0];
  74.                 string dbtype = ca.DbType;
  75.  
  76.                 if (dbtype.StartsWith("NChar") || dbtype.StartsWith("NVarChar")
  77.                     || dbtype.StartsWith("Char") || dbtype.StartsWith("VarChar"))
  78.                 {
  79.                     int index1 = dbtype.IndexOf("(");
  80.                     int index2 = dbtype.IndexOf(")");
  81.                     string dblen = dbtype.Substring(index1 + 1, index2 - index1 - 1);
  82.                     int.TryParse(dblen, out dblenint);
  83.                 }
  84.             }
  85.             return dblenint;
  86.         }

 

Notice the global Stack variable. This is to prevent infinite recursion. As it stands now this code is very slow to run and gets worse the more objects you have linked to your main object. I still think that this is useful for us and has some purpose, especially if your not importing more than a few records at a time. I am not sure how to speed this up so I then thought that maybe we could put an extension method on the string class to check the value as we’re assigning it since it makes sense to only check the properties we’re setting rather than all of them after the fact. I took the code to look at the string property in the above code and created the extension method. The only thing I am not sure about is that I need to also pass in the object we are assigning the string to and the name of the property. So something like:

  1. x.Name = y.Name.CheckLength(x, "Name");

 

Here is the code for the method.

  1. private static string Checklength(this string s, object o, string propName)
  2.         {
  3.             string oReturn = s;
  4.  
  5.             PropertyInfo prop = o.GetType().GetProperty(propName);
  6.  
  7.             object val = prop.GetValue(o, null);
  8.             if (val is string)
  9.             {
  10.                 string value = val.ToString();
  11.                 if (string.IsNullOrEmpty(value))
  12.                     return oReturn;
  13.  
  14.                 int maxLength = GetLengthLimit(prop.GetCustomAttributes(typeof(ColumnAttribute), true));
  15.                 if (maxLength > 0 && value.Length > maxLength)
  16.                     oReturn = value.Substring(0, maxLength);
  17.             }
  18.  
  19.             return oReturn;
  20.         }

 

I haven’t tested it yet because I am not sure if this is the better way to go and because I was hoping to be able to do this in a way that doesn’t require the property name to be passed in as a string. I would be interested to know if anyone else knows a better way to handle this or has any thoughts on the above. As always I hope this is useful.

author: John Nastase | posted @ Thursday, October 28, 2010 11:44 PM | Feedback (2)