Posts

Showing posts from November, 2014

Android - ANR causing process to be killed instead of a Dialog

    Recently, i came across few devices which wouldn't display a ANR dialog ( to give user a chance to wait) instead would just terminate the application process with a dialog saying "Unfortunately, application has stopped". This is the same dialog display for fatal exceptions (both java and native). So why doesn't Android display the usual dialog for an ANR?    How about a bad behavior application to trigger an ANR and test it out on an emulator based on stock AOSP, but in this case no dialog was displayed instead the application window would be closed and the logs would indicate that the process was killed after user request. Turns out, this is a feature where in dialogs aren't shown in certain configurations,     /**      * Decide based on the configuration whether we should shouw the ANR,      * crash, etc dialogs.  The idea is that if there is no affordnace to      * press the on-screen buttons,...

Android - Netflix like Swipe-able Banner (Spotlight)

Image
   Netflix's Android application features a spotlight which has a swipe-able banner view recommending few movies. This could be implemented via a android's ViewPager API and open source Circular Page Indicator.   The pager adapter returns the set of ImageViews and ViewPager invokes adapter APIs based on the user swipe action. A simple adapter looks like, private static class BannerAdapter extends PagerAdapter {         private Map<Integer, ImageView> mBannerImageMap = new HashMap<Integer, ImageView>();         public BannerAdapter(Context context) {             ImageView image1 = new ImageView(context);             image1.setImageResource(R.drawable.beach);             ImageView image2 = new ImageView(context);             image2.setImageResource(R.drawable.northstar);     ...

Android - Musixmatch's floating lyrics for Spotify

Image
   Android developer's blog recently had a post about Musixmatch and Android's unique feature (Intents) being used effectively by the app.   It looks like Musixmatch finds the track info and then displays the lyrics in a floating dialog window via SYSTEM_ALERT_WINDOW. So what kind of intent is musixmatch listening to? Turns out, Spotify has a feature where in an intent is broadcast as soon as Playback is started. This can be turned off by the user via Spotify's native app settings " Device Broadcast Status ". musixmatch just registers for this intent and acts accordingly.     BroadcastReceiver mReceiver = new BroadcastReceiver() {         @Override         public void onReceive(Context context, Intent intent) {             String artist = intent.getStringExtra("artist");             String album = intent.getStringExtra("album");     ...

Android - Identify source of activity creation

     Few applications might want to know the use case in response to which its activity is created to handle internal state etc. Generally, activity is created when it is launched for the first time or in response to a configuration change ( screen orientation, keyboard, language change etc) or when the user resumes the activity from background after a low memory kill. In case of a low memory kill, when the user resumes the activity from the recent apps list, Android creates a new process and starts a new instance of the activity with the previously saved instance state. So how do we identify these three different scenarios? Thanks to an activity API isChangingConfigurations , the logic is quite simple.     private final static String CONFIG_CHANGED = "ConfigurationChanged";     @Override     protected void onSaveInstanceState(Bundle outState) {         super.onSaveInstanceState(outState);       ...

Android - Shortcut to expand and collapse Notification Panel

     Heads up, this post is meant for platform developers and not application developers. One of the annoying thing about Android and other operation systems is having to reach out to expand and collapse the notification bar. This wasn't a problem with devices less than 4.7 inch dimensions. However, this became really annoying with Nexus 6 and its not possible to use one hand to expand the notification bar anymore (not even with large ones).     This could easily be resolved by providing a short cut in the navigation bar which can be handled one hand at all times. Wonder why Google doesn't implement something similar in stock AOSP. Anyways, with the shortcut the usage looks something similar to this,      In this case, the recent apps button is hijacked to illustrate but the actual functionality could very well be provided with an additional button in the Navigation Bar. --- a/packages/SystemUI/src/com/android/systemui/statusbar/...

Android - Enable Navigation Bar in emulator

Image
     Ever landed up with an emulator without Navigation bar and needed it to be enabled quickly? Well, start the emulator as usual and once its ready ensure that the system partition is mounted for write access.         adb shell mount -o rw,remount /system   Next, pull the build.prop from /system and edit it to include this property and push it back to /system        qemu.hw.mainkeys=0 Finally, reboot the framework process,      adb shell ps system_server      adb shell kill <pid> And voila, we have the navigation bar enabled.

Android - Spinner Progress in Notifications

Image
  Thanks to RemoteViews's setViewVisibility, its trivial to show Spinner progress bar in the Notification. Here is an application suggesting new books to download via a background service.     A good feedback would be to show a progress spinner as the book is being downloaded. Here is the notification layout to achieve the same, <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="horizontal"     android:layout_width="match_parent"     android:layout_height="match_parent">     <ImageView         android:id="@+id/preview"         android:layout_width="128dp"         android:layout_height="128dp"/>     <FrameLayout         android:paddingLeft="40dp"         android:layout_gravity="cen...

Android - Orange WiFi Icon in Quick Settings

     Android's Quick Settings occasionally shows an orange WiFi icon of varying strengths and this kind of indicates connectivity issues even though the device is connected to a wireless network. So who is responsible for updating this and what is the trigger entry point?    The actual drawable resources used is specific to the SystemUI application provided as,               R.drawable.ic_qs_wifi_0,               R.drawable.ic_qs_wifi_1,               R.drawable.ic_qs_wifi_2,               R.drawable.ic_qs_wifi_3,               R.drawable.ic_qs_wifi_4,               R.drawable.ic_qs_wifi_0,               R.drawable.ic_qs_wifi_full_1,               R.drawable.ic_qs_wifi_full_2...

Android - Handling errors from Loaders

      Android's Loader API is generalized just to handle results from the background tasks.                               android.content.AsyncTaskLoader< D >  This is fine in most cases as the primary reason to use Loader is to do some operation in background and get the results. However, this by itself is not good enough as background tasks like network operations usually come with strings attached and is associated with multiple error scenarios like network timeout, lost connection, unreachable destination. Besides, the application layer protocol might have other custom errors too. So how to deal with this possibility and update UI accordingly?   Here is a Loader which would fail randomly,     private static class FailSometimeLoader extends AsyncTaskLoader<List> {         int mErrorCode;         List<String...

Android - Check Dialog's Visibility

    Android's Dialog  provides helper isShowing() to determine if the dialog is shown or not, but it doesn't necessarily mean that the Dialog window is shown. The dialog built using the activity's context is requested to be shown via show() . This API involves a communication between multiple processes starting from the application process's Dialog ViewRootImpl and Framework's Window Manager Service and Surface Flinger and there is a tiny delay between when the original request and the actual window being rendered. Eventually, a new Window is created and tracked by framework. This new window would now host the requested dialog. This entire process involves a set of IPC between the application and framework.    However, any attempt to check the status via isShowing() after show() is going to return true.         AlertDialog dialog = builder.create();         dialog.show();         Log.d(TAG, ...

Android - Background tasks across screen orientation (AsyncTaskLoaders)

     One of the annoying tasks for new developers is to deal with the use case where in the activity is destroyed and re created in response to a configuration change like changing orientation from portrait to landscape or vice versa, changing device language, adding a keyboard accessory etc. Handling background tasks in this scenario makes it difficult as most of the ASyncTask implementations hold an explicit reference to the activity or the fragment. This hard dependency could be solved by a broadcast mechanism but then there is a potential race where in broadcast receiver might not be registered as the new instance of the activity might be in the process of recreation and the background task could have fired of the intent to notify the results. This could be solved by using the application context instead of using the activity context to register a broadcast receiver. This would need more work like relaying this event to an appropriate activity and could be complex in...

Android - Styling Action Bar at run time

    Android's style framework helps change the look and feel of UI elements without having to change the source code and invoking View specific APIs at run time. One would assume that this is true for all UI elements. Unfortunately, the Action Bar's Theme can't be changed at run time via applying a different theme. Here is a test code to demonstrate this,   Application has two themes,     <style name="AppTheme2" parent="android:Theme.Holo.Light.DarkActionBar">         <item name="@android:attr/actionBarStyle">@style/MyActionBarStyle2</item>     </style>     <style name="AppTheme1" parent="@android:style/Theme.Holo.Light">         <item name="@android:attr/actionBarStyle">@style/MyActionBarStyle1</item>     </style> Activity's is started with AppTheme1 and changes the theme at runtime based on certain events,       ...

Android - Fragment specific theme

   Few applications might want to apply specific theme for Fragments and this could be easily achieved as long as the Fragment views are recreated when moving across the back stack. This is the case when Fragments are replaced rather than being added ( FragmentTransaction.replace ). The views corresponding to a replaced fragment in back stack would need to created again and added as child of the fragment container. So all that is needed is a layout inflater based on the desired theme and the quick trick is to set the theme before committing the fragment transaction.     private void next(int nextThemeResId, Fragment fragment, String tag, int containerViewId) {         setTheme( nextThemeResId );         FragmentTransaction transaction = getFragmentManager().beginTransaction();         transaction.replace(containerViewId, fragment, tag);         transaction.addToBackStack(null); ...

Android - Back Stack Fragment state loss after multiple screen orientation (onCreate vs onViewStateRestored)

Image
     This post is applicable to activities with following criteria, * Not handling screen orientation (android:configChanges="orientation") * Hosting Fragments in Back stack via replace, with each Fragment responsible to load data over network/database and displaying in respective UI elements. * Fragments saving their state in onSaveInstanceState and restoring it via  onViewStateRestored     The application having such activities usually move from one Fragment to the other based on user action like in this case,     Both Fragments download their data set over network and load the data set into views. When the user in the second Fragment (Dance), the back stack has two fragments and they are managed by the Fragment Manager. Now, as and when the screen orientation changes,    ->  Fragment Manager invokes onSaveInstanceState() on both the fragments.   -> Activity and both Fragments are destroyed ...