Tuesday, May 29, 2012

Android Coding Standards

One of the challenges facing any large development effort is ensuring that all developers follow the same coding standards. Maintaining coding standards, which is "a set or rules or guidelines for formatting code", has numerous benefits including helping lower the cost of code maintenance, enabling new developers to learn the code base faster and overall lower cost of ownership. This link talks about the benefits of coding standards in a very concise and easy to understand way.

http://www.valid-computing.com/benefits-of-coding-standards.html

The Android development team has its own code standards that they use for the Android source. It's published here.  http://source.android.com/source/code-style.html  I try to follow these standards the best that I can, although individual projects may have their own set of standards that should be followed.  The important thing is to have standards and to make sure that everyone uses them.

Thursday, May 24, 2012

Getting the Android id from a URI - Content Provider

I've been working quite a bit with Android content providers on a recent project and one thing that keeps coming up is how to determine the android id (_id) of a record that has just been created via a content provider. The insert statement returns the uri pointing to the row that has been created and this URI ends with the key to the object. In other words the URI can tell you the id, all you have to do is parse it.

 An easy way of doing that parsing is shown below.


Uri uri=getContentResolver().insert(ProviderHelper.determineURI(myCarObj), myCarObj.createContentValues());
Log
String carId = uri.getPathSegments().get(1);

Log.d(TAG, "Content inserted at: " + uri);
Log.d(TAG, "Car_id: " + carId);




05-24 13:49:41.290: D/CarProviderTest(11228): Content inserted at: content://com.supercar.edc.android.contentproviders.Car/car/123


05-24 13:49:41.290: D/CarProviderTest(11228): Car_id: 123)



123 is the Android Id (_id) for the record I just created.






Friday, May 18, 2012

Setting up a dialog template


A real common task is to pop up a confirm/cancel dialog on button clicks.  I've moved this code into a method that I can easily copy and paste into Android Activities and call the dialog with one line of code like the line below. This sample code shows a one button dialog, it's easy to do a two button dialog.  It's easy to set up your custom dialog xml layout which is really similar to any other layout.


showOneButtonDialog(getResources().getString(R.string.errorDialogTitle), message);



 private void showOneButtonDialog(String titleStr, String message) { 

                AlertDialog.Builder builder = new AlertDialog.Builder(WeeksOfPractice.this); 

                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

                View layout = inflater.inflate(R.layout.custom_dialog, 

                          (ViewGroup) findViewById(R.id.layout_root)); 

                TextView title = (TextView) layout.findViewById(R.id.headerTitle); 

                title.setText(titleStr); 

                TextView text = (TextView) layout.findViewById(R.id.text); 

                text.setText(message); 

                ImageView image = (ImageView) layout.findViewById(R.id.image); 

                image.setImageResource(R.drawable.ic_launcher); 

                builder.setView(layout); 

                AlertDialog errorDialog = builder.create(); 

                errorDialog.setButton(getResources().getString(R.string.dialogContinue), 

                          new DialogInterface.OnClickListener() { 

                               public void onClick(DialogInterface dialog, int id) { 

                                    dialog.cancel(); 

                               } 

                          }); 

                errorDialog.show(); 

           }  


Monday, May 14, 2012

Displaying PDF files

I recently had a request by a client to be able to display links that would go to hosted PDF files (files that are out in the cloud somewhere and not resident to the device).  Now there is no guarantee that a particular device has a PDF viewer, say from Adobe installed. And using that viewer would kick the person out of the app anyway when the intent fires.  One easy solution for this is to pass the PDF link to Google documents which would automatically convert the PDF to html and display it.

if (url !=null && url.endsWith(".pdf")) {
Uri uri = Uri.parse("http://docs.google.com/viewer?url=" + url);
Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setDataAndType(uri, "text/html");
startActivity(intent);
}

Sunday, May 13, 2012

XML based Drawables


Android gives you the ability to define shape drawables using xml.Basically these are simple shapes that are great for using as backgrounds or buttons.  The sample below will create a white oval that I use for backgrounds of linear layouts, say for a product description with an image and price. More information is at the link. To add a drawable, pick one of res/drawable directories and save the xml file right to it. For example, I saved a file called shape_white_four_corners.xml to my drawables-hdpi directory.  It'll appear as part of your resource and you can access it just like any other drawable.

http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape


 <?xml version="1.0" encoding="utf-8"?> 

 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"  

 android:background="@color/white"> 

   <gradient android:startColor="@color/white" android:endColor="@color/white" 

       android:angle="270"/> 

   <stroke android:width="0.5dp" android:color="@color/white"/>     

   <padding android:left="7dp" android:top="7dp" 

       android:right="7dp" android:bottom="7dp" /> 

   <corners android:bottomRightRadius="8dp"  

           android:bottomLeftRadius="8dp" 

           android:topLeftRadius="8dp"  

           android:topRightRadius="8dp"/> 

 </shape>  

Wednesday, May 9, 2012

Gmail Attachment Issues

Android will allow a user to put more than one app on it that does something, for example send email So you have your email account app out of box, your gmail account and let's say a third party super duper email app that you can't live without installed on your phone. When you click the email link, it will launch a picker that lists these three apps. You select the one that you want to process the message and it does it. All fine and dandy. Once that picker comes up, you're out of your app and in the picker app. In other words, you don't have much control over error handling. Here's the problem: Gmail can't process attachments. It throws an exception that can't be caught and I can't control what gets processed by the app. For example, having gmail handle a link to an web site instead of putting the attachment right into the message. The only workaround that I have is a link in the message (the images I'm trying to send are on a web server anyway) to the image which should make it work on every app. Android bug report http://code.google.com/p/android/issues/detail?id=27269&q=gmail%20attachments&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars Google http://groups.google.com/a/googleproductforums.com/forum/#!category-topic/gmail/android/PsZ68HiLc_o http://thenextweb.com/mobile/2010/11/10/google-acknowledges-android-gmail-attachment-issues-invites-users-to-help-debug/

Tuesday, May 8, 2012

Debugging HTTP Connections

Most of my Android apps have multiple and sometimes a dozen or so of backend Get, POST and other http api calls. Part of debugging them is figuring out http header request and response data. This code snippet below is a useful utility method that allows you to log out http headers:


public static void logHttpHeaders(Header[] headers)
{
Log.d(TAG,"Logging http headers: " + headers.length );

for (int i = 0; i < headers.length; i++)
    {
    Header h = headers[i];
    Log.d(TAG,"Header: " + h.getName() + " " + h.getValue());
    }

}

Friday, May 4, 2012

Creating an iPhone like PickerWheel

One of the most useful interfaces that iPhone has is the picker wheel which I like to call roulette wheel.  Android date pickers and out of box select boxes are very html-like and not very slick looking. Designing and implementing one that is like the iPhone picker wheel is actually pretty complex/ About two years ago, I put one together for a customer but I was never quite happy with it and it never really felt exactly right.    Luckily the Android open source community has lots of really smart folk, doing some great work and if you're looking for a nice interface to extend in your project, this open source wheel project is what you're looking for.


Android Wheel Control. https://code.google.com/p/android-wheel/

I've used it on a couple of projects and it works great.  It's relatively easy to customize and has some great sample code that pretty much will do what you need to do out of box.  It's one of my favorite Android projects and worth a look to see if it jazzes up your app.