Tuesday, July 16, 2013

Android: Show or Hide UI component with specific interval



When layout or image or any UI component has to be show or hide after specific period of time like 3 secs.
In this case, we think about thread but when we use thread directly and try to update UI, we will be facing "android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Cause:
       This error is common if you tried to send UI events to the UI thread from outside the UI thread.
       The test method Thread tried to interact with the UI outside the UI thread.
      
Suggested:
       Use Handler to solve the cause.

Sample Code:

private TextView titleTV;

/**
 * handler is used for information bar.
 */
final Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);

       titleTV = (TextView) findViewById(R.id.textView1);

       handler.postDelayed(new HideThread(), 3000);

}

private void hideTitle() {
       titleTV.setVisibility(View.INVISIBLE);
}

public class HideThread implements Runnable {

       public void run() {
              try {
                     hideTitle();
              } catch (Exception e) {
                     e.printStackTrace();
              }
       }
}

Thursday, June 20, 2013

Android: Solution for NetworkOnMainThreadException


NetworkOnMainThreadException
Occurs in Runtime Exception
The exception that is thrown when an application attempts to perform a networking operation on its main thread. (NetworkOnMainThreadException)

android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
StrictMode : StrictMode is most commonly used to catch accidental disk or network access on the application's main thread. (StrictMode.ThreadPolicy.Builder)
From above statement, we can conclude there is some network operation is performed in Main Therad.
Exception:
android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
libcore.io.IoBridge.connectErrno(IoBridge.java:127)
libcore.io.IoBridge.connect(IoBridge.java:112)
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
java.net.Socket.connect(Socket.java:842)
org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
.
.
.
android.view.View.performClick(View.java:4204)
android.view.View$PerformClick.run(View.java:17355)
android.os.Handler.handleCallback(Handler.java:725)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:5041)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
dalvik.system.NativeStart.main(Native Method)

Solutions:
Remove Network operation from main thread and use background operations like Services, Async Task
Or
StrictMode implemented from api level 9, so your min android sdk support should be 9

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

Tuesday, June 11, 2013

Android: Unit Test for Custom Content Provider using Roboelectric



Robolectric provides a simple approach to automate unit test case for android by using standard JUnit tests. It runs on any JVM, without needing the emulator or a device.
Advantages of Roboelectric:
No Mocking Frameworks Required

Run Tests Outside of the Emulator

Test Annotations

@RunWith

To run your test with Robolectric, you need to tell JUnit using the @RunWith annotation on your test class:
@RunWith (RobolectricTestRunner.class) // required for Robolectric!
For more details: http://pivotal.github.io/robolectric/user-guide.html
With Robolectric, we can write a small unit test for custom content provide like this.

@RunWith(RobolectricTestRunner.class)
public class BookContentProviderTest {

 private Activity activity;
 private BookProvider bookProvider;
 private ContentResolver contentResolver;

 public static final String AUTHORITY = "com.test.provider.Book";

 public static final String BOOK_TABLE_NAME = "book";

 /**
  * The columns we are interested in from the database
  */
 public static final String[] BOOK_PROJECTION = new String[] {
   BookColumns._ID, // 0
   BookColumns.BOOK_NAME, // 1
 };

 public static final Uri BOOK_URI = Uri.parse("content://" + AUTHORITY + "/"
   + BOOK_TABLE_NAME);

 private String[] bookList = new String[] { "angels and demons", "Book1",
   "Book2", "Book3" };

 @Before
 public void setUp() throws Exception {
  bookProvider = new BookProvider();
  activity = new Activity();
  contentResolver = activity.getContentResolver();

  bookProvider.onCreate();
  ShadowContentResolver.registerProvider(AUTHORITY, bookProvider);
 }

 @Test
 public void testContentProvider() {

  insertBook(new Book("53bfc0b980b0", "angels and demons"));
  insertBook(new Book("53bfc0b980b3", "Book1"));
  insertBook(new Book("53bfc0b980b1", "Book2"));
  insertBook(new Book("53bfc0b980b2", "Book3"));

  Cursor cursor = contentResolver.query(BOOK_URI, BOOK_PROJECTION, null,
    null, BookColumns.DEFAULT_SORT_ORDER);

  cursor.moveToFirst();

  Assert.assertTrue(cursor.getCount() == 4);

  if (cursor.getCount() != 0) {
   do {
    Assert.assertEquals(bookList[cursor.getPosition()],
      cursor.getString(cursor
        .getColumnIndex(BookColumns.BOOK_NAME)));
   } while (cursor.moveToNext());
  }

 }

 private void insertBook(Book book) {
  contentResolver.insert(BOOK_URI, getContentValue(book));
 }

 private ContentValues getContentValue(Book book) {
  ContentValues values;
  values = new ContentValues();
  values.put(BookColumns._ID, book.getBookId());
  values.put(BookColumns.BOOK_NAME, book.getName());
  return values;
 }
}