Guide: Google Services for Android : In-App Purchase:

It was a long time since my last update here and this time I want to talk about a topic that
has a great importance to me, as I manage a lot of it in recent at my current work location.
For this reason I have decided to take a moment and write an informative guide for the
integration of In-App Purchase feature in your application.

So to integrate In-App purchase feature in you application you have to follow a few simple steps:

1. First of all we will add a permission to the Manifest file:

<uses-permission android:name="com.android.vending.BILLING"/>

2. Next you will need to get a license key for the In-App Purchase process from the Google Play Administration Console. You can get it in a couple of ways one is by clicking the “Prepare Store Listing” button when adding a new application to the store.
To start this process press the Add new application button at the main screen of the developer’s console:

add_new_application

2.1. Then enter a default language for your application.
2.2. Give you application a title to display in Google Play store.
2.3. Press the Prepare Store Listing button to add additional information for the application.

Alternatively you could chose to upload an application’s APK that has the permission from
first step and this way Google will know that our app has an In App Purchase feature and will let us get the key.

To get the key open the developer console and go to the Services & APIs section.
Under the LICENSING & IN-APP BILLING section. You will find a YOUR LICENSE KEY FOR THIS APPLICATION which will have you application’s license key. You will need to add it to your application later on.

3. Now that you have a key it’s time to add an in app product to you application, in the developer console open the In-App Products section and press the Add New Product button, you will receive the
following window:

in_app_product_explained

3.1. Selected the manage product, manage product are product that Google manages for
you in their data bases, basically you can latter on query their databases for the status of
this item for the user of your application.

3.2. Enter an id for this product (Important: this id can’t be changed after it entered) and press Continue. Next a page will be opened when you will have to
add some other details for this product as it Name (that will be shown for the users), Price
and Description.

Now that we finished with the console configuration lets start implementing the feature in our
application:

4. First of all we will need to download the Google Play Billing Library from the
SDK Manager. Once have done it, this will result in downloading an example project
that will be located at the following folder:

/extras/google/play_billing

4.1. You will need to copy from this project the IInAppBillingService.aidl file including all of it’s folder’s structure. So this file must be added into the following path: com.android.vending.billing

4.2. In addition one of this project’s folders is called utils, and includes Google’s Helper classes to handle the In-App Purchase flow. So you will need to copy this folder to your project.

At the end of this process your project structure should look like this:

project_structure

5.1. Now lets start with the coding. First of all we will setup the helper class:

public class MainActivity extends Activity {
    IabHelper mHelper;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        String base64EncodedPublicKey = "<your license key goes here>";
        mHelper = new IabHelper(this, base64EncodedPublicKey);
        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
            public void onIabSetupFinished(IabResult result) 
            {
                if (!result.isSuccess()) {
                    Log.d(TAG, "Problem setting up in-app billing: " + result);
                    return;
                }

                // Have we been disposed of in the meantime? If so, quit.
                if (mHelper == null) return; 
           

                // IAB is fully set up. Now, let's get an inventory of stuff we own.
                Log.d(TAG, "Setup successful. Querying inventory.");
            });
        } 
.....
}

5.2. Next we will need to add product details (its id) to the application, as well as to add some
kind of a trigger to make a purchase of the in-app product, So I will add a button called bBuyFirstItem to my layout and add those lines to my code:

//an int to count the product.
int firstCount = 0;

//product id in the google play (the one you entered when adding the product in the developers console)
static final String SKU_FIRST_ITEM = "first";

// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10001;

Button bBuyFirstItem = (Button) findViewById(R.id.bBuyFirstItem);

bBuyFirstItem.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d(TAG, "Launching purchase flow for first item.");
        String payload = "";
        mHelper.launchPurchaseFlow(this, SKU_FIRST_ITEM, RC_REQUEST, mPurchaseFinishedListener, payload);
    }
});

5.3. Now we need to add a trigger for successful purchase, and the verifyDeveloperPayload method:

 // Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
    Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);

    // if we were disposed of in the meantime, quit.
    if (mHelper == null) return;

    if (result.isFailure()) { return; }

    if (!verifyDeveloperPayload(purchase)) { return; }

    Log.d(TAG, "Purchase successful.");

    if (purchase.getSku().equals(SKU_FIRST_ITEM)) {
        // bought 1 first item, consume it.
        Log.d(TAG, "Purchase is first item. Starting item consumption.");
        firstCount++;
    }
};

/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
    String payload = p.getDeveloperPayload();

    /*
     * TODO: verify that the developer payload of the purchase is correct. It will be
     * the same one that you sent when initiating the purchase.
     *
     * WARNING: Locally generating a random string when starting a purchase and
     * verifying it here might seem like a good approach, but this will fail in the
     * case where the user purchases an item on one device and then uses your app on
     * a different device, because on the other device you will not have access to the
     * random string you originally generated.
     *
     * So a good developer payload has these characteristics:
     *
     * 1. If two different users purchase an item, the payload is different between them,
     *    so that one user's purchase can't be replayed to another user.
     *
     * 2. The payload must be such that you can verify it even when the app wasn't the
     *    one who initiated the purchase flow (so that items purchased by the user on
     *    one device work on other devices owned by the user).
     *
     * Using your own server to store and verify developer payloads across app
     * installations is recommended.
     */

     return true;
}

5.4. You could also query the Google servers for managed products to get
the status of a product for the user account:

//to run a query run this method at the end of the helper object setup process
mHelper.queryInventoryAsync(mGotInventoryListenerMain);

//You also will need to create the listener:
IabHelper.QueryInventoryFinishedListener mGotInventoryListenerMain = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
       Log.d(TAG, "Query inventory finished.");

       // Have we been disposed of in the meantime? If so, quit.
       if (mHelper == null) return;

       // Is it a failure?
       if (result.isFailure()) { return; }

       Log.d(TAG, "Query inventory was successful.");

       /*
        * Check for items we own. Notice that for each purchase, we check
        * the developer payload to see if it's correct! See
        * verifyDeveloperPayload().
        */

        Purchase firstItemPurchase = inventory.getPurchase(SKU_FIRST_ITEM);
        boolean mIsFirstItem = (firstItemPurchase != null && verifyDeveloperPayload(firstItemPurchase));
        if (mIsFirstItem) {
             mHelper.consumeAsync(firstItemPurchase, null);
        }
        Log.d(TAG, "User owns: " + (mIsFirstItem ? "FIRST ITEM" : "NOT FIRST ITEM"));
        Log.d(TAG, "Initial inventory query finished; enabling main UI.");
    }
};

That’s it for now, hope this will help you to start with integrating the In-App Purchase
feature in your application. Enjoy and Stay tuned :)

Guide: Google Maps V2 for Android : Update InfoWindow with an Image Asynchronously:

One of the needs that raise up in my last project was to update an Google Maps InfoWindow
with an image that I receive asynchronously from the web. Now the problem with this is
that the the view of the InfoWindow on the map is not the actual view you created in the xml
editor but an image rendered from it. If you look at the docs you will see:

Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (for example, after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.

Now that we cleared that, another thing that I want to mention is that for loading the image I use
the Picasso library by Square that you can read more about in this blog post I wrote:
Guide: How to load images asynchronously into a ListView.

Next it’s important to mention that the layout file you provide for the InfoWindow must include it’s
own background, because you are not going to be provided with the default Google Maps
InfoWindow background. So here is the code for the custom InfoWindowAdapter:

private class CustomInfoWindowAdapter implements InfoWindowAdapter {

    private View view;
    LayoutInflater inflater = null;

     public CustomInfoWindowAdapter(LayoutInflater inflater) {
         //Inflating the InfoWindow view.
         this.inflater = inflater;
         view = inflater.inflate(R.layout.info_window, null);
     }

     @Override
     public View getInfoContents(final Marker marker) {
         //Re-show InfoWindow if it already shown
         if ( App.getInstance().currentlyClickedMarker != null && App.getInstance().currentlyClickedMarker.isInfoWindowShown() ) {
             App.getInstance().currentlyClickedMarker.hideInfoWindow();
             App.getInstance().currentlyClickedMarker.showInfoWindow();
         }
         return null;
     }

     @Override
     public View getInfoWindow(final Marker marker) {
         App.getInstance().currentlyClickedMarker = marker;  	    
         TextView venueName = (TextView) view.findViewById(R.id.info_window_name);
         TextView venueAddress = (TextView) view.findViewById(R.id.info_window_address);
         ImageView venueLogo = (ImageView) view.findViewById(R.id.ivLogo);
         //Get the Image from web using Picasso and update the info contents		
         Picasso.with(getActivity()).load(App.getInstance().getVenueByAddress(marker.getSnippet()).getLogo()).into(venueLogo, new Callback() {	
             @Override
             public void onSuccess() {
                 getInfoContents(marker);
             }
  				
             @Override
             public void onError() {}
         });
         venueName.setText(marker.getTitle());
         venueAddress.setText(marker.getSnippet());
         return view;
    }
}    

Finally you will have to set this adapter to the GoogleMap object:

map.setInfoWindowAdapter(new CustomInfoWindowAdapter(getActivity().getLayoutInflater()));
June 20, 2014Emil Adjiev Comments Off
FILED UNDER :Guide , Guide - Android Development , Guide - Google Maps for Android

Android Project: CUPS

My recent project that I’m currently working on is the CUPS – Unlimited Coffee application.
This application is part of a coffee subscription service that will allow you to buy coffee
in very attractive prices, in Israel and USA. You can take a look at the application
by downloading it from Google Play Store:

CUPS – Unlimited Coffee

Here are some screen shots from the application:

You are welcome to download, take a look at and rate the application : )

Have a great day and stay tuned.

February 17, 2014Emil Adjiev No Comments »
FILED UNDER :My Project

Guide: How to load images asynchronously into a ListView:

Recently I worked on a ListView that required to load preaty large images into
the ListView view so I encounter the all mighty OutOfMemory exception every
Android developer will encounter some time during his developer live.

So for this topic I have decide to concentrate on the current libraries that allow you
to load images in an asynchronous way into your desired ImageViews in your ListViews:

1. So first I want to talk about the nostra13 / Android-Universal-Image-Loader:

this is a well known library that has been used widely by the Android developers,
I won’t be heavy on code on this one, as I think that his documentation is very sufficient.
The main thing you have to do is to initialize the ImageLoader object in your Application class,
and providing it with a ImageLoaderConfiguration object:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // Create global configuration and initialize ImageLoader with this configuration
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
            ...
            .build();
        ImageLoader.getInstance().init(config);
    }
}

Check out the link for all the different configurations you can make when building the
ImageLoaderConfiguration class. Next to actually load an image inside your adapter you should use this:

imageLoader.displayImage(imageUri, imageView, displayOptions, new ImageLoadingListener() {
    @Override
    public void onLoadingStarted(String imageUri, View view) {
        ...
    }
    @Override
    public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
        ...
    }
    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
        progress.setVisibility(View.GONE);
    }
    @Override
    public void onLoadingCancelled(String imageUri, View view) {
        ...
    }
});

And use the onLoadingComplete method to preform and action when image
is finished loading like removing a ProgressBar.

2. The next library is newer and is less known among developers Square / Picasso,
You can find the GitHub page here.From my usage I must say that it does a great job
and provide you with some useful methods along side with a fading-in affect when image is finished loading out of the box.

So the deal here is even simpler, to load an image into an ImageView all you have to do is this:

Picasso.with(context).load(url).into(imageView);

If you want a finishing call back it not problem as well:

Picasso.with(context).load(url).into(imageView, new Callback() {
			
    @Override
    public void onSuccess() {
        progress.setVisibility(View.GONE);
    }
			
    @Override
    public void onError() {
        progress.setVisibility(View.GONE); 
    }
);

An option i really liked with this library is a call back you can use before the image
is applied to the ImageView:

target = new Target() {
    @Override
    public void onBitmapLoaded(Bitmap image, LoadedFrom arg1) {
        imageView.setImageBitmap(Util.getCroppedBitmap(image));
    }
	
    @Override
     public void onPrepareLoad(Drawable arg0) {}
				
    @Override
    public void onBitmapFailed(Drawable arg0) {
        imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.person));
    }
};
Picasso.with(context).load(url).into(target);

3. Currently I’m checking the Volley library that was presented to us by Google team at 2013 I/O.
This library is not concentrated only on image loading, but on most of our application network
tasks. By their description it shows great promise. And very soon I will update this post with
my conclusions. You can fork it from here.

UPDATE:
Well after a few day of usage I came to conclusion that for now I will stay away from the Volley
library for loading images and use a more dedicated library for that. The reasons for that will
come later but for now I will explain how to use it. Now to use the Volley library is a little
more difficult then to use the two previously described libraries.

First you will need to change your XML layout file that contains the ImageView you want to
populate with an image and to replace this ImageView with a NetworkImageView like so:

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/image"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:adjustViewBounds="true"
    android:scaleType="fitXY" />

Next get the this view using the right casting:

NetworkImageView networkImageView = (NetworkImageView) findViewById(R.id.image);

And finally set the image from the URL:

holder.venueImage.setImageUrl(url, ImageCacheManager.getInstance().getImageLoader());

If you look closely to the last line of code, you will see that the second parameter of the
setImageUrl is an ImageLoader object. I’m supplying it using the ImageCacheManager
object. The reason I do that is because Volley doesn’t provide L2 caching out of the box
and you will need to provide your own implementation for that.

For that purpose I found this blog post very useful as he provides a full working
implementation for you. Just follow the post, you will find there a GitHub repository with
an implementation you can use: Google I/O 2013: Volley Image Cache Tutorial

If you are using this implementation you will need to initialize your ImageCacheManager
in your Application class:

public class App extends Application 
{
    private static int DISK_IMAGECACHE_SIZE = 1024*1024*10;
    private static CompressFormat DISK_IMAGECACHE_COMPRESS_FORMAT = CompressFormat.PNG;
    private static int DISK_IMAGECACHE_QUALITY = 100;  //PNG is lossless so quality is ignored but must be provided

    public void onCreate() 
    {
        super.onCreate();
        init();
    }

    private void init() {
        RequestManager.init(this);
        createImageCache();
    }
	
    /**
     * Create the image cache. Uses Memory Cache by default. Change to Disk for a Disk based LRU implementation.  
     */
    private void createImageCache(){
        ImageCacheManager.getInstance().init(this,
            this.getPackageCodePath()
            , DISK_IMAGECACHE_SIZE
            , DISK_IMAGECACHE_COMPRESS_FORMAT
            , DISK_IMAGECACHE_QUALITY  
            , CacheType.MEMORY);
    }
}

Now the reason that currently I have decided not to use this library is that for some reason
I have found it lacking some basic functionality the two other libraries had. The first problem
is that I didn’t find a way to get a finish call back on loading the image (so I could remove the
progress bar as I did before…). The second problem I encountered is that when you use Volley
in a ListView and you swipe it so fast the image doesn’t has enough time to load, Volley will
stop it’s loading until the next time you will come back to it. I didn’t find a way to change this behavior.

And that’s it for now, stay tuned.

November 29, 2013Emil Adjiev 2 Comments »
FILED UNDER :Guide , Guide - Android Development

Guide: 9-Patch Tools and Explanation:

I think that 9-patch textures are underestimated in Android development and should be
used in almost everywhere while you developing a complex UI that should fit a lot of
screen sizes. But it’s really important first to fully understand how those 9-patch textures
work and how you use them to you advantage.

There is a lot of great material on the web to get the hang of it but I found this blog post
by Radley Marx really helpful for me to understand the needed concepts. If you haven’t read
it I strongly suggest you to do so. As simple as I can put it the 9-Patch textures are textures
that can stretch and be filled with content accordingly to guide lines that you add to the texture.
Those guide lines are removed when the texture is being applied and won’t show in your app.

Once you have understand the main concepts of creating a 9-Patch texture you will find that
adding a one pixel guide lines to a desired texture is not always as simple as it might seem.
I found my self something struggle to produce the desired texture that will stretch as I wanted.

Luckily I have found some tools on the web that will do this job for you:

1. The first tool is the Simple Nine-patch Generator from the Android Asset Studio.
Actually if you haven’t seen this page yet then I strongly suggest you to go over
Android Asset Studio there are really handy tools that you can use
in order to produce a Holo like textures with your desired color and much more.

2. The second tool is draw9patch.com. what I found convinient in this tool is
that you can see the result of the fill guide lines in the preview as well and you can see the
affect of the guide lines you change in real time.

Finally I would like to present you with a real life example where I used a 9-patch
to solve a UI design problem. This was a question I asked on SO and followed an answer
I received:

Is there a way to implement rounded corners to a Mapfragment?

That’s it for today, stay tuned.

July 23, 2013Emil Adjiev No Comments »
FILED UNDER :Guide , Guide - Android Development

Guide: Google Maps V2 for Android: Draw Driving Direction on Map:

This is again one of those popular questions that I stumble upon, I already gave here an
answer for this one, but I decided to put it in here anyways as a post. So let get started.
First of all if you are not familiar with Google’s new Maps API, I suggest you to first of all read
this post: Google Maps API V2 Key to get your own API key which is required to
integrate Google maps in your application. Next follow this post: Google Maps API V2
to actually integrate Google Maps in your application.

If you already have a map integrated in your application and you want to add driving navigation
to it, you came to the right place. Here I will present you the code that will allow you to paint a line
(Polyline object on your map) to show the directions from point A to B. But first I would like
to point your to this quote:

Google Maps/Google Earth APIs Terms of Service

  Last updated: May 27, 2009
...
10. License Restrictions. Except as expressly permitted under the Terms, or unless you
have received prior written authorization from Google (or, as applicable, from the
provider of particular Content), Google's licenses above are subject to your adherence
to all of the restrictions below. Except as explicitly permitted in Section 7 or the
Maps APIs Documentation, you must not (nor may you permit anyone else to):
...
10.9 use the Service or Content with any products, systems, or applications for or in
connection with:

(a) real time navigation or route guidance, including but not limited to turn-by-turn
route guidance that is synchronized to the position of a user's sensor-enabled device;

and may be disabled for certain apps (somehow, at least on Android)... FromGeocode
scraping in .NET conversation:
This is not allowed by the API terms of use. You should not scrape Google Maps to
generate geocodes. We will block services that do automated queries of our servers.

Bret Taylor
Product Manager, Google Maps

I might be mistaken but from my understanding of this quote Google does not allow to show
driving navigation using Google Maps. Now that we covered that I will show you how you can
paint on the map.

1. So lets start with the GMapV2Direction class, this class is responsible to
make a request to Google Directions API and get the navigation instruction for 2 LatLng points:

public class GMapV2Direction {
    public final static String MODE_DRIVING = "driving";
    public final static String MODE_WALKING = "walking";

    public GMapV2Direction() { }

    public Document getDocument(LatLng start, LatLng end, String mode) {
        String url = "http://maps.googleapis.com/maps/api/directions/xml?"
                + "origin=" + start.latitude + "," + start.longitude
                + "&destination=" + end.latitude + "," + end.longitude
                + "&sensor=false&units=metric&mode=" + mode;

        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();
            HttpPost httpPost = new HttpPost(url);
            HttpResponse response = httpClient.execute(httpPost, localContext);
            InputStream in = response.getEntity().getContent();
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(in);
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getDurationText (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("duration");
        Node node1 = nl1.item(0);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "text"));
        Log.i("DurationText", node2.getTextContent());
        return node2.getTextContent();
    }

    public int getDurationValue (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("duration");
        Node node1 = nl1.item(0);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "value"));
        Log.i("DurationValue", node2.getTextContent());
        return Integer.parseInt(node2.getTextContent());
    }

    public String getDistanceText (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("distance");
        Node node1 = nl1.item(0);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "text"));
        Log.i("DistanceText", node2.getTextContent());
        return node2.getTextContent();
    }

    public int getDistanceValue (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("distance");
        Node node1 = nl1.item(0);
        NodeList nl2 = node1.getChildNodes();
        Node node2 = nl2.item(getNodeIndex(nl2, "value"));
        Log.i("DistanceValue", node2.getTextContent());
        return Integer.parseInt(node2.getTextContent());
    }

    public String getStartAddress (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("start_address");
        Node node1 = nl1.item(0);
        Log.i("StartAddress", node1.getTextContent());
        return node1.getTextContent();
    }

    public String getEndAddress (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("end_address");
        Node node1 = nl1.item(0);
        Log.i("StartAddress", node1.getTextContent());
        return node1.getTextContent();
    }

    public String getCopyRights (Document doc) {
        NodeList nl1 = doc.getElementsByTagName("copyrights");
        Node node1 = nl1.item(0);
        Log.i("CopyRights", node1.getTextContent());
        return node1.getTextContent();
    }

    public ArrayList getDirection (Document doc) {
        NodeList nl1, nl2, nl3;
        ArrayList listGeopoints = new ArrayList();
        nl1 = doc.getElementsByTagName("step");
        if (nl1.getLength() > 0) {
            for (int i = 0; i < nl1.getLength(); i++) {
                Node node1 = nl1.item(i);
                nl2 = node1.getChildNodes();

                Node locationNode = nl2.item(getNodeIndex(nl2, "start_location"));
                nl3 = locationNode.getChildNodes();
                Node latNode = nl3.item(getNodeIndex(nl3, "lat"));
                double lat = Double.parseDouble(latNode.getTextContent());
                Node lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                double lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));

                locationNode = nl2.item(getNodeIndex(nl2, "polyline"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "points"));
                ArrayList arr = decodePoly(latNode.getTextContent());
                for(int j = 0 ; j < arr.size() ; j++) {
                    listGeopoints.add(new LatLng(arr.get(j).latitude, arr.get(j).longitude));
                }

                locationNode = nl2.item(getNodeIndex(nl2, "end_location"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "lat"));
                lat = Double.parseDouble(latNode.getTextContent());
                lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));
            }
        }

        return listGeopoints;
    }

    private int getNodeIndex(NodeList nl, String nodename) {
        for(int i = 0 ; i < nl.getLength() ; i++) {
            if(nl.item(i).getNodeName().equals(nodename))
                return i;
        }
        return -1;
    }

    private ArrayList decodePoly(String encoded) {
        ArrayList poly = new ArrayList();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;
        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;                 shift += 5;             } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;
            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;                 shift += 5;             } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng position = new LatLng((double) lat / 1E5, (double) lng / 1E5);
            poly.add(position);
        }
        return poly;
    }
}

2. Because finding the desired route is a potentially long running task,
we need to place this in a AsyncTask in order to avoid blocking the UI-Thread.
So we are going to create the following GetDirectionsAsyncTask:

public class GetDirectionsAsyncTask extends AsyncTask<Map<String, String>, Object, ArrayList>
{
    public static final String USER_CURRENT_LAT = "user_current_lat";
    public static final String USER_CURRENT_LONG = "user_current_long";
    public static final String DESTINATION_LAT = "destination_lat";
    public static final String DESTINATION_LONG = "destination_long";
    public static final String DIRECTIONS_MODE = "directions_mode";
    private MapFragmentActivity activity;
    private Exception exception;
    private ProgressDialog progressDialog;

    public GetDirectionsAsyncTask(MapFragmentActivity activity)
    {
        super();
        this.activity = activity;
    }

    public void onPreExecute()
    {
        progressDialog = new ProgressDialog(activity);
        progressDialog.setMessage("Calculating directions");
        progressDialog.show();
    }

    @Override
    public void onPostExecute(ArrayList result)
    {
        progressDialog.dismiss();
        if (exception == null)
        {
            activity.handleGetDirectionsResult(result);
        }
        else
        {
            processException();
        }
    }

    @Override
    protected ArrayList doInBackground(Map<String, String>... params)
    {
        Map<String, String> paramMap = params[0];
        try
        {
            LatLng fromPosition = new LatLng(Double.valueOf(paramMap.get(USER_CURRENT_LAT)) , Double.valueOf(paramMap.get(USER_CURRENT_LONG)));
            LatLng toPosition = new LatLng(Double.valueOf(paramMap.get(DESTINATION_LAT)) , Double.valueOf(paramMap.get(DESTINATION_LONG)));
            GMapV2Direction md = new GMapV2Direction();
            Document doc = md.getDocument(fromPosition, toPosition, paramMap.get(DIRECTIONS_MODE));
            ArrayList directionPoints = md.getDirection(doc);
            return directionPoints;
        }
        catch (Exception e)
        {
            exception = e;
            return null;
        }
    }

    private void processException()
    {
        Toast.makeText(activity, activity.getString(R.string.error_when_retrieving_data), 3000).show();
    }
}

3. No we would like to use this AsyncTask to find the road direction from one
location to another. To make the usage of this AsyncTask a little bit more convenient I have
created the following findDirections method in my MapFragmentActivity:

public void findDirections(double fromPositionDoubleLat, double fromPositionDoubleLong, double toPositionDoubleLat, double toPositionDoubleLong, String mode)
{
    Map<String, String> map = new HashMap<String, String>();
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LAT, String.valueOf(fromPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.USER_CURRENT_LONG, String.valueOf(fromPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DESTINATION_LAT, String.valueOf(toPositionDoubleLat));
    map.put(GetDirectionsAsyncTask.DESTINATION_LONG, String.valueOf(toPositionDoubleLong));
    map.put(GetDirectionsAsyncTask.DIRECTIONS_MODE, mode);

    GetDirectionsAsyncTask asyncTask = new GetDirectionsAsyncTask(this);
    asyncTask.execute(map);
}

What I’m doing here is creating a HashMap with the needed coordinates
(Start Lat and Long, End Lat and Long), Passing them to the AsyncTask and executing it.

4. Next, we will create the following handleGetDirectionsResult method,
to handle the AsyncTask result and to actually paint the directions Polyline on the map.

public void handleGetDirectionsResult(ArrayList directionPoints)
{
    Polyline newPolyline;
    GoogleMap mMap = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
    PolylineOptions rectLine = new PolylineOptions().width(3).color(Color.BLUE);
    for(int i = 0 ; i < directionPoints.size() ; i++)
    {
        rectLine.add(directionPoints.get(i));
    }
    newPolyline = mMap.addPolyline(rectLine);
}

5. Finally to get the direction we need to run the findDirections method
with the desired locations in code like this:

findDirections(SGTasksListAppObj.getInstance().currentUserLocation.getLatitude(),
SGTasksListAppObj.getInstance().currentUserLocation.getLongitude(),
clickMarkerLatLng.latitude, clickMarkerLatLng.longitude, GMapV2Direction.MODE_DRIVING );

The final result should look something like that:

direction_blue

As you see a blue directions line is drown on the map, for showing the way you need to
go for your destination. And that’s it, you are finished.

6. UPDATE: Due to many requests I have created a small Android project that
demonstrates the usage of this code. You can download this project from here.
The project show how to navigate from Amsterdam to Paris or to Frankfurt, just
remember to add your Google Maps API V2 Key in the manifest file.

Enjoy and stay tuned.

Guide: Android: Parsing JSON Files with Gson and Native Objects:

I see a lot of questions as for how to parse JSON object in android, So I decides to write
a small guide to demonstrate how it’s done. Android platform has build-in tools for dealing
with those parsing tasks so I going to talk about those today. I also going to
show you a basic use of Google’s Gson library.

When we talk about JSON files, important to say that JSON (stand for JavaScript Object Notation) is, and I quote Wikipedia:

“a text-based open standard designed for human-readable data interchange. It is
derived from the JavaScript scripting language for representing simple data structures
and associative arrays, called objects.”

So JSON standard was basically designed to interchange data between different devices
over the internet. There are actually two main structures in JSON files which are Objects and
Arrays. Those will be the objects we will use in our code in order to parse those files.
Lets dive into an example:

Say we received a JSON file that represents a class and a list of students with their grades,
and this file looks like this:

{
    "Class":{
        "Class_Id": "A2",
        "Class_Type": "Science",
        "Class_Student_Count": 23,
        "Class_Studens": [
            {
                "Student_Id": "123456789",
                "Student_Name": "DavStudent_Id",
                "Student_Age": 23,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            },
            {
                "Student_Id": "987654321",
                "Student_Name": "Dan",
                "Student_Age": 25,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            },
            {
                "Student_Id": "123789456",
                "Student_Name": "Smith",
                "Student_Age": 30,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            },
            {
                "Student_Id": "987321654",
                "Student_Name": "Jhon",
                "Student_Age": 18,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            },
            {
                "Student_Id": "789123456",
                "Student_Name": "Leon",
                "Student_Age": 19,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            },
            {
                "Student_Id": "654987321",
                "Student_Name": "Philip",
                "Student_Age": 22,
                "Student_Grades": [
                    { "Course_Name": "Mathematics", "Course_Grade": 95},
                    { "Course_Name": "Biology", "Course_Grade": 80},
                    { "Course_Name": "English", "Course_Grade": 86}
                ]
            }
        ]
    }
}

As you can see this JSON file describes a students class with class details. In addition it
contains a list of class’s students while each one of them contains a list as well with the
student’s related course grades. It’s a fairly simple valid JSON file and at the moment I will
parse only the students list part, but before that I would like to share the following service
with you: http://jsonlint.com/. It will allow you to validate your JSON file and make
sure that what you receive from any web service is in fact a valid JSON file.

1. First we will create the relevant classes for parsing:
Student Class:

public class Student 
{
    private String studentId;
    private String studentName;
    private int studentAge;
    private List<Grade> studentGrades;
     
	public Student() {
		super();
		this.studentGrades = new ArrayList<Grade>();
	}
	public String getStudentId() {
		return studentId;
	}
	public void setStudentId(String studentId) {
		this.studentId = studentId;
	}
	public String getStudentName() {
		return studentName;
	}
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	public int getStudentAge() {
		return studentAge;
	}
	public void setStudentAge(int studentAge) {
		this.studentAge = studentAge;
	}
	public List<Grade> getStudentGrades() {
		return studentGrades;
	}
	public void setStudentGrades(List<Grade> studentGrades) {
		this.studentGrades = studentGrades;
	}
    
	public void addGradeToGradesList(Grade grade)
	{
		this.studentGrades.add(grade);
	}
	@Override
	public String toString() {
		return "Student [studentId=" + studentId + ", studentName="
				+ studentName + ", studentAge=" + studentAge
				+ ", studentGrades=" + studentGrades + "]";
	}	
}

Grade Class:

public class Grade 
{
	private String course;
	private int courseGrade;
	
	public String getCourse() {
		return course;
	}
	public void setCourse(String course) {
		this.course = course;
	}
	public int getCourseGrade() {
		return courseGrade;
	}
	public void setCourseGrade(int courseGrade) {
		this.courseGrade = courseGrade;
	}
	@Override
	public String toString() {
		return "Grade [course=" + course + ", courseGrade=" + courseGrade + "]";
	}	
}

Those classes are really self-explanatory so I’m not going to dwell on them much.

2. Second, I will create the JSON parsing class:

import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;

public class JSONParsingClass 
{
	private static final String TAG = JSONParsingClass.class.getSimpleName();
	
	//static final String for parsed elements
	//Class elements
	public static final String STUDENTS_LIST_ELEMENT = "Class_Studens";
	
	//Student elements
	public static final String STUDENT_ID = "Student_Id";
	public static final String STUDENT_NAME = "Student_Name";
	public static final String STUDENT_AGE = "Student_Age";
	public static final String STUDENT_GRADE_LIST = "Student_Grades";
	public static final String CLASS = "Class";
	
	//Grade elements
	public static final String COURSE_NAME = "Course_Name";
	public static final String COURSE_GRADE = "Course_Grade";

	//Native method for parsing json file
	public static List<Student> NativeJsonParseMethodForStudents(String jsonString) {
		try{
			//Creating list object for storing the parsed students
			List<Student> studentsList = new ArrayList<Student>();
			
			//Creating JSON object from string
			JSONObject json = new JSONObject(jsonString);
			
			//Getting "Class" element from JSON file
			JSONObject classElement = json.getJSONObject(CLASS);

			//Making sure that students list array exists
			if (!classElement.isNull(STUDENTS_LIST_ELEMENT))
			{
				//Getting students array
				JSONArray array = classElement.getJSONArray(STUDENTS_LIST_ELEMENT);
				
				//Creating empty json object for students loop
				JSONObject currentStudent;
				
				//looping all the students and adding them parsed one by one to the list
				for (int i = 0 ; i < array.length() ; i ++){
					currentStudent = array.getJSONObject(i);
					
					//Method to parse students and add them to the list
					addCurrentStudentToStudentsList(currentStudent, studentsList);
				}
				//Returning parsed students list
				return studentsList;
			}
			else
			{
				Log.d(TAG, "Students List is Null");
				return null;
			}
		} catch (Exception e) {
		   	Log.e("EXC", "Error", e);
		   	return null;
		}
	}
	
	//Method to parse students and added them to the list
	private static void addCurrentStudentToStudentsList(JSONObject currentStudent, List<Student> studentsList) 
	{
		//Initializing Student Object
		Student student = new Student();
		
		//Creating empty list for student's grades.
		List<Grade> studentGrades = new ArrayList<Grade>();
		try {
			//Parsing student's details.
			student.setStudentId(currentStudent.getString(STUDENT_ID));
			student.setStudentName(currentStudent.getString(STUDENT_NAME));
			student.setStudentAge(currentStudent.getInt(STUDENT_AGE));	
			
			//Making sure that student's grades list array exists
			if (!currentStudent.isNull(STUDENT_GRADE_LIST))
			{
				//Getting grades array
				JSONArray array = currentStudent.getJSONArray(STUDENT_GRADE_LIST);
				
				//Creating empty json object for grades loop
				JSONObject currentGrade;
				
				//looping all the student's grades and adding them parsed one by one to the list
				for (int i = 0 ; i < array.length() ; i ++){
					currentGrade = array.getJSONObject(i);
					
					//Method to parse grades and add them to the list
					addCurrentGradeToGradesList(currentGrade, studentGrades);
				}
			}
			//Setting student's grades
			student.setStudentGrades(studentGrades);
			
			//Adding student to the list
			studentsList.add(student);
			Log.d(TAG, "Added student: "+ student.toString()); 
		} catch (JSONException e) {
			Log.e(TAG, "Exception thrown on adding student to students list: "+ e.toString());
			e.printStackTrace();
		}	
	}
	
	//Method to parse grades and add them to the list
	private static void addCurrentGradeToGradesList(JSONObject currentGrade, List<Grade> studentGrades) {
		Grade grade = new Grade();
		Log.d(TAG, "currentGrade object: " + currentGrade.toString());
		try 
		{
			//Parsing grade's details
			grade.setCourse(currentGrade.getString(COURSE_NAME));
			grade.setCourseGrade(currentGrade.getInt(COURSE_GRADE));
			
			//Adding grade to the list
			studentGrades.add(grade);
			
		} catch (JSONException e) {
		Log.e(TAG, "Exception thrown on adding grade to grades list: "+ e.toString());
		e.printStackTrace();
		}
	}	
}

I added a comment above each line of code, So this class should be more then understandable
as well. And basically you are done, you have a parsed list of all the students with their grades
from the JSON file. You can practice by creating the “Class” class and try to parse it and add
the students to it’s list.

Gson Library Usage:

In the next part of this guide I will show you a way to cut down on the written code for parsing
this simple file by using the Gson library, because lets admit it, it’s whole lot of code
for parsing such a simple file.

1. So the first step for using Gson library as with any other library is of course to download it,
head to Gson Download and download the latest version.

2. Next, as before we will have to create the class we are going to populate with the parsed
data, but this time with a small difference:

Student Class for Gson:

import com.google.gson.annotations.SerializedName;

public class Student 
{
    @SerializedName(JSONParsingClass.STUDENT_ID)
    private String studentId;
	
    @SerializedName(JSONParsingClass.STUDENT_NAME)
    private String studentName;
	
    @SerializedName(JSONParsingClass.STUDENT_AGE)
    private int studentAge;
	
    @SerializedName(JSONParsingClass.STUDENT_GRADE_LIST)
    private List<Grade> studentGrades;

    //Rest of code is unchanged...    

Grade Class for Gson:

import com.google.gson.annotations.SerializedName;

public class Grade 
{
    @SerializedName(JSONParsingClass.COURSE_NAME)
    private String course;
	
    @SerializedName(JSONParsingClass.COURSE_GRADE)
    private int courseGrade;
    
    //Rest of code is unchanged...

It possible to omit the Gson annotations if you use the same variable names for the class
parameters as they appear in the JSON file, but because this is not the case those annotations are necessary.

3. Now, I will added another method to my JSONParsingClass:

private static void addCurrentStudentToStudentsListUsingGson(JSONObject currentStudent, List<Student> studentsList) 
{
    Gson gson = new Gson();
    Student student = gson.fromJson(currentStudent.toString(), Student.class);
    studentsList.add(student);
}

4. Finally, I will replace this line of code:

addCurrentStudentToStudentsList(currentStudent, studentsList);

In the

public static List<Student> NativeJsonParseMethodForStudents(String jsonString)

Method, with this line of code:

addCurrentStudentToStudentsListUsingGson(currentStudent, studentsList);

So we basically replaced the two long parsing methods: addCurrentStudentToStudentsList
and addCurrentGradeToGradesList from the first part of this guide with this single 3 lines of
code method: addCurrentStudentToStudentsListUsingGson. And that’s it, Now you can
parse JSON files in your application in the native way or use the Gson library.

One last thing, during the writing of this post, I have created an Android project with all the source
code presented here. You can download this project from here.

Enjoy and stay tuned.

May 18, 2013Emil Adjiev 11 Comments »
FILED UNDER :Guide , Guide - Android Development , Guide - JSON Parsing

Guide: Android: Crash Reports and Usage Monitoring:

Well you reached a step where you have completed your application and want
to test it or even publish it to the Google Play store. At this point (It’s strongly recommended
to do that even before that) it’s very important to integrated some sort of crash reports
service in your application and could be very useful to integrate some kind of usage
monitoring system as well.

So, today I’m going to talk about those features and more specifically I’m going to talk
about integration of two crash report services:

1. Crittercism
2. ACRA with BugSense back-end.

Both of those services can be used for free, but got paid programs as well.
I’m going to talk about one usage monitoring system as well named:
3. Flurry.
Lets start with the crash reports. So how is it done:

1. Well for Crittercism the deal is very simple, head to their site: www.crittercism.com,
and sign in. You will need to download the jar file from Documentation for Android section.
Once you did that and added the jar file to the /libs folder of your project you are ready to start
configuring it. Open your Apps section and create an application for which you would like to
receive crash reports. Press the:

Untitled

button, and enter the application details. When you finish press the REGISTER APP button at
the bottom of the page. Open your Apps page again and you will see the newly
added application under the Registered Apps section. Click on the app name to enter
it’s configurations and go to the Settings page (red), under “To initiate Crittercism for this
Application:”
you will find a row of code (green) you will have to integrate in your application
in order for the crash reports service to work:

Untitled5

You should integrate this line in the first Activity of your application in the onCreate() method:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Crittercism.init(getApplicationContext(), "516a6c4e46b7c26e6f000002");
    // rest of code here...
}

Add this Activity to the Manifast file:

<activity android:name="com.crittercism.NotificationActivity"/>

Finally you need to add the following three permissions to your Manifest file:

<!--  Internet Permission  -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--  Crittercism Permissions  -->
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.GET_TASKS"/>

2. The second crash reporting service is greatly popular among Android developers:
Application Crash Report for Android or ACRA in short. up until not long ago
this service was used with Google Doc back-end to store the crash logs. this use of
Google Doc have became deprecated by Google, and they have asked developers nicely
not to use their service for this purpose.

So I searched for another back-end service that will work with ACRA and found out that
BugSense provide this kind of service. What you need to do as before is to head
to their site and sign up. Next, you will receive a dashboard screen, in it create a new
project that will represent the project you want to receive error reports for. Press the:

add project

button, and enter the application details like: Project Name, Billing Account, Platform (Technology) and another application details. Open your My projects page again and you will
see the newly added application:

new project

You can see that with the new project you receive an ApiKey(red) that you will use next to integrate ACRA in your project. To do that first head to acra.ch and download the
last .jar file from the Quick Setup section. As before add the jar file to the /libs folder of your project.

Now you can start integrate ACRA in your code, all you need to do is to add 2 lines to your application class:

import org.acra.*;
import org.acra.annotation.*;

@ReportsCrashes(formUri = "http://www.bugsense.com/api/acra?api_key=1e76b702", formKey="")
public class MyApplication extends Application 
{
    @Override
    public void onCreate() 
    {
        // The following line triggers the initialization of ACRA
        super.onCreate();
        ACRA.init(this);
        // rest of code here...
    }
}		

So as you can see you need to add the @ReportsCrashes annotation right before the class
definitions, where you would replace the api_key, with the key you were given from BugSense
when you registered your app. Second line would be:

ACRA.init(this);

to initialize ACRA monitoring. As with the first crash service don’t forget to add here the internet permission as well:

<!--  Internet Permission  -->
<uses-permission android:name="android.permission.INTERNET"/>

3. Now for the usage monitoring system: Flurry:
As with the other two services, we need to register so head to www.flurry.com, sign up for
the service, and open the Applications tab in your dashboard screen. click the Add a New Application option from the up-right corner, choose the platform of your project (Android in our case), pick a name for the project and select it’s category. Finally press the Create App button.

Next, you will receive the following screen:
flurry

Here as you can see you receive Your unique application key (1) and you have a button to
download the relevant SDK file for you platform (2). Download the SDK and as before integrate
it into the /libs folder of your application. Now for Flurry integration you need to add in each Activity of your application were you want to monitor user actions, those lines to start and stop monitoring:

@Override
protected void onStart()
{
    super.onStart();
    FlurryAgent.onStartSession(this, "65KYTTCTDCMT7J69S7XT");
}
	 
@Override
protected void onStop()
{
    super.onStop();		
    FlurryAgent.onEndSession(this);
}

To monitor an event you should add this line in the relevant position in your code:

FlurryAgent.onEvent("Event text");

If you want to monitor parameters as well then you need to pass a HashMap of parameters to the FlurryAgent like this:

final HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("String key", "String value");
FlurryAgent.logEvent("Text relevant to parameters", parameters);

As before, don’t forget to add the internet permission to your project:

<!--  Internet Permission  -->
<uses-permission android:name="android.permission.INTERNET"/>

And that it. Now you can and should monitor your application for errors and usage.
Enjoy and stay tuned.

April 23, 2013Emil Adjiev 1 Comment »
FILED UNDER :Guide , Guide - Android Development

Guide: Android: Use Camera Activity for Thumbnail and Full Size Image:

Today I have decided to show you how to use the build in camera Activity to
Take thumbnail and full size images. The reason for that is that this is a common problem
and many people get confused as for why do they get a low resolution image when they are
using the build in camera Activity for taking images in their Android application
(I was one of those people).

But first I would like to stop and explain why do you need thumbnail images in your app.
The problem with mobile devices as we all know is that they are low on resources (CPU,
Memory, Storage, etc.. today clearly this statement becomes less and less true), as for this
reason the Android OS was designed to allow a single application use only a very limited
amount of memory at run time.

That means that you can’t take a full 5 or 8 megapixels image and load it into memory just to
show it inside a small ImageView. Well, you can, but on the second or third image your
application will simply crash with an java.lang.OutOfMemoryError. So clearly you have
to care always to use the image with the most low resolution but yet satisfies with it quality at run time.

Back to where I started, people get confused because there are several ways to perform this
operation and I will show you them today:

Thumbnail Image:

Actually this will be the easiest way to take an image using the camera and to save it in
you application. The problem with this is that this image is very low resolution and is
not fit for displaying on a full mobile screen:

1. First of all define:

public static final int CAPTURE_IMAGE_THUMBNAIL_ACTIVITY_REQUEST_CODE = 1888; 

This will be your code so you could read the result of the camera Activity. You can
define here any number you would like.

2. Next fire an intent that will start an Activity for result.

Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, CAPTURE_IMAGE_THUMBNAIL_ACTIVITY_REQUEST_CODE);

3. Finally receive the result and save it:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{  
    //Check that request code matches ours:
    if (requestCode == CAPTURE_IMAGE_THUMBNAIL_ACTIVITY_REQUEST_CODE) 
    {
        //Check if your application folder exists in the external storage, if not create it:
        File imageStorageFolder = new File(Environment.getExternalStorageDirectory()+File.separator+"Your application Folder");
        if (!imageStorageFolder.exists())
        {
            imageStorageFolder.mkdirs();
            Log.d(TAG , "Folder created at: "+imageStorageFolder.toString());
        }

        //Check if data in not null and extract the Bitmap:
        if (data != null)
        {
            String filename = "image";
            String fileNameExtension = ".jpg";
            File sdCard = Environment.getExternalStorageDirectory();
            String imageStorageFolder = File.separator+"Your application Folder"+File.separator;
            File destinationFile = new File(sdCard, imageStorageFolder + filename + fileNameExtension);
            Log.d(TAG, "the destination for image file is: " + destinationFile );
            if (data.getExtras() != null)
            {
                Bitmap bitmap = (Bitmap)data.getExtras().get("data");
                try 
                {
                    FileOutputStream out = new FileOutputStream(destinationFile);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                    out.flush();
                    out.close();
                } 
                catch (Exception e) 
                {
                    Log.e(TAG, "ERROR:" + e.toString());
                }
            }
        }
    }
}

You can see that in this case we are getting our image from the Extras of the intent under
the “data” key. We cast it to a Bitmap and save it to a file using an FileOutputStream.
But actually we didn’t had to save it to file and could use the bitmap straight forward.

Full Size Image:

Well the big difference here is if we want to produce a high quality image from the
camera Activity we don’t have a choice but to save it into file and then use:

1. So First of all as before we need to create a static int that will be our requestCode:

public static final int CAPTURE_IMAGE_FULLSIZE_ACTIVITY_REQUEST_CODE = 1777; 

2. Next we fire again the same intent to start Activity for result but this time with a little difference:

Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
File file = new File(Environment.getExternalStorageDirectory()+File.separator + "image.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, CAPTURE_IMAGE_FULLSIZE_ACTIVITY_REQUEST_CODE);

and the difference in this case is with this line: intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

Here we are actually passing an URI as an extra to the intent in order to save the image at this location
when it will be taken.

3. Finally we will receive the result in onActivityResult:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{  
    //Check that request code matches ours:
    if (requestCode == CAPTURE_IMAGE_FULLSIZE_ACTIVITY_REQUEST_CODE) 
    {
        //Get our saved file into a bitmap object:
       File file = new File(Environment.getExternalStorageDirectory()+File.separator + "image.jpg");
       Bitmap bitmap = decodeSampledBitmapFromFile(file.getAbsolutePath(), 1000, 700);
    }
}

When decodeSampledBitmapFromFile method is:

public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) 
{ // BEST QUALITY MATCH
    
    //First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, options);

    // Calculate inSampleSize, Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    int inSampleSize = 1;

    if (height > reqHeight) 
    {
        inSampleSize = Math.round((float)height / (float)reqHeight);
    }
    int expectedWidth = width / inSampleSize;

    if (expectedWidth > reqWidth) 
    {
        //if(Math.round((float)width / (float)reqWidth) > inSampleSize) // If bigger SampSize..
        inSampleSize = Math.round((float)width / (float)reqWidth);
    }

    options.inSampleSize = inSampleSize;

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(path, options);
}

For both cases don’t forget to add the relevent camera permissions to the manifest file:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

And that’s it, now you can add the build in camera capabilities to your application and take
images with the quality you want. Enjoy.

April 7, 2013Emil Adjiev 11 Comments »
FILED UNDER :Guide , Guide - Android Development

Guide: Android – MultiClickable ListView:

Well today I want to talk about implementation of a multiclickable list.
And what do I mean by that? Well what I mean is that every list item has
more then one location where you can press it following by different operation.

So lets for example take a row where you want to place a CheckBox, ImageView
and a TextView while all of them are clickable. Meaning that you can click the
row it self for going to another Actvity for more details on the row, check its
CheckBox or press the ImageView to perform another operation.

So what you should do is:

1. First create an XML layout file for your ListView row:

<LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <CheckBox 
        android:id="@+id/cbCheckListItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="10dp" />
    <TextView
        android:id="@+id/tvItemTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="item string" />
    <ImageView
        android:id="@+id/iStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:contentDescription="@drawable/ic_launcher"
        android:src="@drawable/ic_launcher" /> 
</LinearLayout>

2. Second in your java code define a ViewHolder, a ViewHolder
is designed to hold the row views and that way operating more quickly.

static class ViewHolder 
{
    TextView title;
    CheckBox checked;
    ImageView changeRowStatus;
}

3. Now we have to define CustomArrayAdapter, using the array adapter
we can define precisely what is the desired output for each row based on the content of this
row or it’s position. We can do so by overriding the getView method:

private class CustomArrayAdapter extends ArrayAdapter<RowData>
{	
    private ArrayList<RowData> list;
    
    //this custom adapter receives an ArrayList of RowData objects.
    //RowData is my class that represents the data for a single row and could be anything.
    public CustomArrayAdapter(Context context, int textViewResourceId, ArrayList<RowData> rowDataList) 
    {
        //populate the local list with data.
        super(context, textViewResourceId, rowDataList);
        this.list = new ArrayList<RowData>();
        this.list.addAll(rowDataList);
    }
		
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        //creating the ViewHolder we defined earlier.
        ViewHolder holder = new ViewHolder();) 
        
        //creating LayoutInflator for inflating the row layout.
        LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //inflating the row layout we defined earlier.
        convertView = inflator.inflate(R.layout.row_item_layout, null);
        
        //setting the views into the ViewHolder.
        holder.title = (TextView) convertView.findViewById(R.id.tvItemTitle);
        holder.changeRowStatus = (ImageView) convertView.findViewById(R.id.iStatus);
        holder.changeRowStatus.setTag(position);
 
        //define an onClickListener for the ImageView.
        holder.changeRowStatus.setOnClickListener(new OnClickListener() 
        {			
            @Override
            public void onClick(View v) 
            {
                Toast.makeText(activity, "Image from row " + position + " was pressed", Toast.LENGTH_LONG).show();
            }
        });
        holder.checked = (CheckBox) convertView.findViewById(R.id.cbCheckListItem);
        holder.checked.setTag(position);

        //define an onClickListener for the CheckBox.
        holder.checked.setOnClickListener(new OnClickListener() 
        {		
            @Override
            public void onClick(View v)
            {
                //assign check-box state to the corresponding object in list.    
                CheckBox checkbox = (CheckBox) v;
                rowDataList.get(position).setChecked(checkbox.isChecked());
                Toast.makeText(activity, "CheckBox from row " + position + " was checked", Toast.LENGTH_LONG).show();	 
            }
        });

        //setting data into the the ViewHolder.
        holder.title.setText(rowDataList.get(position).getName());
        holder.checked.setChecked(rowDataList.get(position).isChecked());

        //return the row view.
        return convertView;
    }
}

4. Now you need to set this adapter, as the adapter of your ListView.
this ListView can be created in java or using an XML file, in this case I’m using a list that was
defined in the XML file using the “list” id:

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout); 
    ListView list = (ListView)findViewById(R.id.list);
    CustomArrayAdapter dataAdapter = new CustomArrayAdapter(this, R.id.tvItemTitle, rowDataList);
    list.setAdapter(dataAdapter);
}

5. Finally if we want to be able to press the row it self and not only a certain view in it
we should assign an onItemClickListener to the ListView:

list.setOnItemClickListener(new OnItemClickListener() 
{
    public void onItemClick(AdapterView<?> parent, View view,int position, long id) 
    {
        Toast.makeText(activity, "row " + position + " was pressed", Toast.LENGTH_LONG).show();
    }
});
March 31, 2013Emil Adjiev 6 Comments »
FILED UNDER :Guide , Guide - Android Development