Tuesday, February 3, 2015

Fetch all Contacts from Contacts Content Provider in Android

Here I am going to explain how to fetch all contacts from Contacts content provider. As you already know content provider is used to share data between applications. Here we will get the data from contacts content provider to our application. First we have to create an object of ContentResolver.

 ContentResolver contentResolver = getContentResolver()  

Then query the content resolver using the Contacts URI.

 Cursor contactsCursor = resolver.query(Contacts.CONTENT_URI, null, null, null, null);  

After querying we will get the contacts ID. Using contacts ID, we can get the phone number,


 String id = contactsCursor.getString(contactsCursor.getColumnIndex(Contacts._ID));  
 // to get phone number of respective contact  
 Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + " = ?", new String[] { id }, null);  
 String phoneNumber = "";  
 if (phoneCursor.moveToFirst()) {  
      phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(Phone.NUMBER));  
 }  
 phoneCursor.close();  

Then to get the contacts name, contacts photo and email, use the below code

 String name = contactsCursor.getString(contactsCursor.getColumnIndex(Contacts.DISPLAY_NAME));  
 String photoUri = "";  
 photoUri = contactsCursor.getString(contactsCursor.getColumnIndex(Photo.PHOTO_URI));  
 // to get email id of respective contact  
 Cursor emailCursor = resolver.query(Email.CONTENT_URI, null, Email.CONTACT_ID + " = ?", new String[] { id }, null);  
 String email = "";  
 if (emailCursor.moveToFirst()) {  
      email = emailCursor.getString(emailCursor.getColumnIndex(Email.ADDRESS));  
 }  
 emailCursor.close();  

Here some tips for SQLITE query. To limit the records, in query() API for the last parameter first sort for an attribute, then limit the records using limit ,

Eg: Contacts._ID DESC LIMIT 10,10

Here contacts will be sorted in descending order by _ID and we will get 10 records from 10 to 20.

The new query looks like this,

 Cursor contactsCursor = resolver.query(Contacts.CONTENT_URI, null, null, null, Contacts._ID+" DESC LIMIT 10,10");  

We can get the full source code by clcicking HERE

The screenshots are here as follows,


Also by clicking on the selected contact, it will call to that particular contact, if it has a phone number.

Monday, February 2, 2015

Driving direction between two locations in Android

Here, I am explaining the driving direction between two locations in google map. It is an utility function. Here we are passing two locations to a method called "showMapFromLocation", first convert the location to corresponding latitude and longitude. Then using launch google map using intent. Here I just hard coded the package and launcher activity of google map. It is better to check the application (google map) is already there in the device using packagemanager.

The utility function is as follows,

 private void showMapFromLocation(String src, String dest) {  
           double srcLat = 0, srcLng = 0, destLat = 0, destLng = 0;  
           Geocoder geocoder = new Geocoder(this, Locale.getDefault());  
           try {  
                if (isOnline()) {  
                     List<Address> srcAddresses = geocoder.getFromLocationName(src,  
                               1);  
                     if (srcAddresses.size() > 0) {  
                          Address location = srcAddresses.get(0);  
                          srcLat = location.getLatitude();  
                          srcLng = location.getLongitude();  
                     }  
                     List<Address> destAddresses = geocoder.getFromLocationName(  
                               dest, 1);  
                     if (destAddresses.size() > 0) {  
                          Address location = destAddresses.get(0);  
                          destLat = location.getLatitude();  
                          destLng = location.getLongitude();  
                     }  
                     String desLocation = "&daddr=" + Double.toString(destLat) + ","  
                               + Double.toString(destLng);  
                     String currLocation = "saddr=" + Double.toString(srcLat) + ","  
                               + Double.toString(srcLng);  
                     // "d" means driving car, "w" means walking "r" means by bus  
                     Intent intent = new Intent(android.content.Intent.ACTION_VIEW,  
                               Uri.parse("http://maps.google.com/maps?" + currLocation  
                                         + desLocation + "&dirflg=d"));  
                     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK  
                               & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);  
                     intent.setClassName("com.google.android.apps.maps",  
                               "com.google.android.maps.MapsActivity");  
                     startActivity(intent);  
                }  
           } catch (IOException e) {  
                Log.e(TAG, "Error when showing google map directions, E: " + e);  
           } catch (Exception e) {  
                Log.e(TAG, "Error when showing google map directions, E: " + e);  
           }  
      }  

We can select which mode of driving direction we need according to the flag "dirflg".
    - dirflg = d, means driving by car
    - dirflg = w, means by walking and
    - dirflg = r, means by bus

The screenshots are like,

One last thing is we have to add google play services library to show the google maps.

Tuesday, January 27, 2015

Gesture detection and scrollview issue

In one of my latest application when I implemented ViewFlipper with gesture listener, I come across a strange issue. All child of ViewFlipper are scrollViews. I implemented simple gesture listener like when swipe to left or right will take to the next scrollView. But the issue was swipe functionality is not working in scrollView. If the ViewFlipper child are any other layout like Linearlayout, swipe functionality is working fine. As usual, I debugged and found that, we have to override the dispatchTouchEvent(MotionEvent e) of activity class.

The dispatchTouchEvent() will look like this,
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return gestureDetector.onTouchEvent(ev);
}
Where gestureDetector is an instance of android.view.GestureDetector class.

Reference:
http://stackoverflow.com/questions/8330187/gesture-detection-and-scrollview-issue

Thursday, January 22, 2015

How to avoid MEMORY LEAKS in Android

Memory leaks means resources which are not available for garbage collection. GC will free resources which are not referenced. Sometimes a single reference can prevent a large set of objects from being garbage collected. For example, some static variables which are referenced in an activity may not be for GC, because as long as the reference exists, the Activity will be kept in memory, leaking all of its views.

Code snippet from Romain Guy is as,

private static Drawable sBackground;

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);

  TextView label = new TextView(this);
  label.setText("Leaks are bad");

  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);

  setContentView(label);
}
Here, the static drawable sBackground will leak.

The solution here is when the activity gets destroyed, release the drawable in destroy and unbind all callbacks


Here, our onDestroy() will look like this,


protected void onDestroy() { 
super.onDestroy();
sBackground.setCallbacks(null);
sBackground = null;
}

So that the drawable sBackground will be available for GC and can prevent memory leak when activity gets destroyed.

Another common cause for memory leak is non-static inner classes in an Activity. This commonly comes when creating fragments in an Activity. Either create static inner classes or create stand alone classes.

Reference:
http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html
http://stackoverflow.com/questions/6567647/avoid-memory-leaks-on-android

Tuesday, November 18, 2014

Open Contacts using Intent and get Contact in onActivityResult()

Here, I am launching contacts from my app using a button click. I am opening contacts which have phone numbers. Here we are launching contacts using startActivityForResult, so while returning back to the app, app will get the selected contact info in onActivityResult() of Activity class.

The code snippet is as,

 ((Button) findViewById(R.id.btn_openContacts)).setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                     Intent i = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);  
                     i.setType(Phone.CONTENT_TYPE);  
                     startActivityForResult(i, PICK_CONTACT);  
                }  
 });  
onActivityResult() will be look like this,
 @Override  
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
           super.onActivityResult(requestCode, resultCode, data);  
           Log.i(TAG, "onActivityResult()");  
           if (requestCode == PICK_CONTACT) {  
                if (resultCode == Activity.RESULT_OK) {  
                     Uri contactsData = data.getData();  
                     CursorLoader loader = new CursorLoader(this, contactsData, null, null, null, null);  
                     Cursor c = loader.loadInBackground();  
                     if (c.moveToFirst()) {  
                          Log.i(TAG, "Contacts ID: " + c.getString(c.getColumnIndex(Contacts._ID)));  
                          Log.i(TAG, "Contacts Name: " + c.getString(c.getColumnIndex(Contacts.DISPLAY_NAME)));  
                          Log.i(TAG, "Contacts Phone Number: " + c.getString(c.getColumnIndex(Phone.NUMBER)));  
                          Log.i(TAG, "Contacts Photo Uri: " + c.getString(c.getColumnIndex(Photo.PHOTO_URI)));  
                     }  
                }  
           }  
      }  

Here I am just getting the details and getting in the Logcat. Just to verify I am getting the contact details

The screenshots are,

Tuesday, April 8, 2014

CalledFromWrongThreadException in Android

I got CalledFromWrongThreadException when I tried to update UI from another thread. I have two threads in my app, one our main UI thread and another for network operations. So when I tried to update UI from "network thread", I got the exception CalledFromWrongThreadException.

Solution:
The solution for this is update the UI in UI thread. For this, just put the update UI statements inside runOnUiThread block. First get the activity context, and call runOnUiThread(). Like,
runOnUIThread(new Runnable() {
public void run() {
...
}
});
Happy Coding

Sunday, March 9, 2014

Recap: A look back for Android, from late 2008 to early 2014

I was not active in blogging for a while, and after a long gap, posting a new one. All my previous posts are from my app development experience in Android. This one is a little different. I like to tell about brief history of Android from my experience and updates

Android changed a lot from the initial days. Late 2008 and early 2009's, where Android phones are just entering into the smartphone market and first phone was from T-Mobile called G1. During that time, testing of the apps are mainly on emulator, so when I first tested my app in an real Android phone, I was so excited. G1 is almost like what we see in an emulator. It was Android SDK v 1.0. Now, jelly bean and the latest kitkat arrived, which are improved a lot, also in the process, Android evolved as a strong mobile OS as well as matured a lot in terms of security, user experience and added more features.

In the global smartphone market, 80% share belongs to Android. In five years from 0 to 80% share is a big achievement. Of this, 80% of Android phones are Android version ICS (API level 14 and above). In this majority of the share goes to Samsung. Samsung share in Android phones is about 63%. That means Out of 80 Android phones, 50 are from Samsung.

Tablets

Now Android is capturing Tablet market also, In 2013, Android takes 62% market share of tablet as Apple's share declines.

Note:
The numbers in this post are got from various sites. I did my best to get the numbers accurate and updated.

Androidians