Easier Bug Reporting on 4.2

With the recent release of an updated Jelly Bean version, i.e, 4.2, there have been quite some new things to awe you.

These are two things that could probably make a developers life easier.

  • Take bug report — immediately takes a screen shot and dumps device state information to local file storage, then attaches them to a new outgoing email message.
  • Power menu bug reports — Adds a new option to the device power menu and quick settings to take a bug report (see above).
Remember, while you were testing your app on a bus, or you were away from your desktop/laptop and got a dreaded crash!! You, so eagerly want to have a look at the logcat, or even save the logcat output for later investigation. And most of the times, I don’t have SendLog, which I could fire up, and send me the logs.
With 4.2, it’s already built-in to your phone. Here are a few screenshots, that give you an idea.
Enable this option from the Settings Page.

Hold the power button, to see the option to capture a “Bug Report”
Happy Coding…

Android Themes: A dialog without a title


Most of the times, I have seen developers not leveraging the power of themes and styles. Themes and styles are a great way to easily create UI that are  manageable and compatible for various platforms. Here’s the official documentation that explains styles and themes in details, and I consider this portion of documentation to be equally important to any developer working with Android.

For the example of this post, we will see how to make a dialog, a custom dialog, not to have a title. The easiest way to do this, is through code byt writing this snippet in your custom dialog class.

requestWindowFeature(Window.FEATURE_NO_TITLE);

Dialog with Title on Android 2.2


Dialog with no title on Android 2.2

While this would work anyway, and would also be compatible with all the versions of Android. But, it’s a good idea to use more of your themes and styles in your programming, so that your code base is maintainable and your apps would behave and feel consistently. Using styles and themes makes it very easy to tweak or adapt to various platform versions and/or device sizes and resolutions. So, let’s get in.

The application tag, has a configurable attribute called “android:theme” with which you can set a theme to your application as a whole. You can also specify themes for individual themes for all your activities separately. Sounds nice!!! But, let’s stick to one theme for our application as a whole for simplicity.

For this example, we have a theme (it’s actually called a style), called MyThemeSelector as shown below. This is specified in the styles.xml in your values folder. Notice, your custom theme is a child of the Theme, which is one of the system’s default themes.

<resources>        <style name=”MyThemeSelector” parent=”@android:style/Theme”></style></resources>

Ideally, you should also declare your custom theme to extend one of the basic themes that are available with platforms on or above Honeycomb. For example, here we have created another styles.xml in a folder called values-v11, which looks like this.

<resources>
        <style name=”MyThemeSelector” parent=”@android:style/Theme.DeviceDefault.Light”></style>
</resources>

So, your basic theme is now compatible with both older versions and versions greater than Honeycomb. By this, I mean, that, when you run the app, your app would adapt to the platform that it is running on, and would give a consistent look and feel for your users.

Now, coming back to the main problem. “Creating a dialog without title”. Here also, we would use themes, as against code. Here are the two new themes that you would be declaring.

For values folder: (Platform versions older than Honeycomb)

<style name=”My.Theme.Dialog” parent=”@android:style/Theme.Dialog”>
            <item name=”android:windowNoTitle”>true</item>
</style>
<style name=”MyThemedDialog” parent=”@style/My.Theme.Dialog”></style>

For values-v11 folder: (Platform version for Honeycomb and above)

<style name=”My.Dialog.Theme” parent=”@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar”></style>
<style name=”MyThemedDialog” parent=”@style/My.Dialog.Theme”></style>

There’s a subtle difference between the two versions. Of course, other than the parent classes. In older platform versions, there wasn’t a version of the Dialog theme without a title bar. So, what we do here, is to extend the basic Dialog them, and overwrite an attribute, so that our custom “My.Theme.Dialog” is a dialog without a title bar.

But, for Honeycomb and above, the platform itself provides a version of the Dialog theme, without the title bar (or the Action Bar).

And finally, the last step for getting everything to work is set the theme to your dialogs.

MyDialog dialog = new MyDialog(this, R.style.MyThemedDialog);
dialog.setTitle(“Here’s my title”);
dialog.show(); 

Why didn’t we use “My.Theme.Dialog” directly? Well, we could still try and tweak the theme for older versions, in the values folder, by adding a few more attributes.

Dialog with title on Android 4.1


Dialog with no title on Android 4.1

As you can see, for both older and newer platforms, the app runs by adapting itself and gives a consistent look and feel. You didn’t have to do much with your code. 
15 lines of XML is the MAGIC here!!!!  (I didn’t count though, just guessing)

Sample project here.

Drag and Drop (Honeycomb/ICS)

Drag and drop is already available with Honeycomb and up. In this example, we will see how to implement a simple Drag and Drop Operation.

We have a ListView with some items. The other half of the screen would have a drop area which has a single TextView. We will see, how to drag items from the ListView, drop them into the drop area, which will update the TextView with the list item’s title, and also, that particular item would be removed from the ListView.

We will trigger the drag operation, when you long tap on an item in the ListView. After the drag operation is started, you will see a floating view of the selected item, which you can move around the screen. When you approach the drop area, the background of the drop area would change, which means that you can now drop your item. Once you leave the item, the TextView inside the drop area will show the text of the selected item.

This should also work on Ice Cream Sandwich. You can find the whole source code here. The code is quite self-explanatory. But, if you have any queries, let me know through the comment form. There are a few comments in the code to help you.

Flip animation in Android

I love animations. Let’s see the video first. If you are excited, go peek at the code.
In this example, the main layout contains two ImageView widgets with two different images that are to be animated. The image views actually overlapp each other, at first, but as the animation starts, only one of them is visible at a time, while the other is invisible.
For the animation, we are using a FlipAnimator class, which extends the Animation class. Here is how we need to initialize and setup the animation.
FlipAnimator animator = new FlipAnimator(imageViewOriginal, imageViewFlip,
                        imageViewFlip.getWidth() / 2, imageViewFlip.getHeight() / 2);
 if (imageViewOriginal.getVisibility() == View.GONE) {
                animator.reverse();
 }
 layout.startAnimation(animator);

 There is a small check to tell the animator where to reverse the animation. This is not the perfect way, but you will get an idea. To initialize the animator, you will need to pass the original view and the flipped view and the x and y position of the axes about which it will be flipped.

The animator, internally uses a AccelerateDecelerateInterpolator.
“An interpolator where the rate of change starts and ends slowly but
accelerates through the middle.”

The main logic of the animation is written inside this method:
protected void applyTransformation(float interpolatedTime, Transformation t)

You can find the whole source code here

References:
http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html 

Understanding Intents and Intent-Filters in Android

Intents or Intent messaging is the Android’s way to pass messages/information to various components of Android. An Intent object contains information that the target component can act upon. Through Intents, your apps can trigger Activities, Services and Broadcast Receivers.
The most common use of intents in any application is to directly launch
an Activity or Service to perform action on the data being passed with
the Intent object.

A sample use of Intent is shown in the following example.
1. To launch an Activity

Intent intent = new Intent(context, TagetActivity.class);
startActivity(intent);

2. To launch a Service

Intent intent = new Intent(context, TargetService.class);
startService(intent);

To pass some data within your intents you need pass them within the Intent object like this.

intent.put(key, value);

This way you can pass basic data-types that are supported by the
Intent class. In these examples, we are specifying the component names
explicitly, i.e, TagetActivity activity and TargetService service. These
intents are examples of Explicit Intents wherein you specify the target component that you want to handle your data.

There would be situations where you would want the user to choose the
target component, or to put in another way, the target component is
determined dynamically at run-time depending on various factors. For an
example, you would like to write a E-Mail app. The basic requirement
would be that whenever a user clicks on an e-mail address, your app
should be triggered, and it should be designed to capture the e-mail
address that was clicked. This is where, Implicit Intents
come into picture. Since, the e-mail address link that the user clicks
on might not necessarily be a part of your application, you do not have
the privilege of launching your Compose Activity on the click event of
the link. What would you do in such a case?

What happens when the e-mail link is clicked?
When an email link is clicked, the app would create an Implicit Intent
setting it up with the proper data and broadcast it. Something like
this:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.put(Intent.EXTRA_EMAIL, {email addresses}];
startActivity(intent);

In the above code snippet, we can see that the Intent here doesn’t
specify the component name. However, it specifies an action and the list
of email addresses. For this example, we just need to pass a string
array with just one email address that the user has clicked on.

How would Android know which activity should be launched (or service
for example). In such cases, Android tries to find the best match, i.e,
the component that can handle such a payload. In case it finds multiple
components, it gives the user a choice to make. For instance, if you
have multiple email clients installed and all of them can handle such
type of Intents, the user gets a list of all these apps (see image). He
can then select one which would launch that particular component
(Activity for this example). If it fails to find any components to
handle this Intent, an exception will be thrown (ActivityNotFoundException
in this case). Here we have two email applications that can handle this
intent. The user is given a choice to select one of them when an e-mail
link is clicked. Depending on the user’s choice, the corresponding
activity will be launched.

How do we write an Activity that can handle such Intents?

We have to specify or rather design one of our activity, the compose
screen of our email client that can handle such intents. For that, we
need to specify Intent-Filters for this specific activity in the AndroidManifest.xml file.

<activity android:name=”.ComposeActivity”
    android:label=”@string/app_name”>
    <intent-filter android:label=”@string/app_name”>
         <action android:name=”android.intent.action.SEND” />
         <data android:scheme=”mailto” />
         <category android:name=”android.intent.category.DEFAULT”/>
    </intent-filter>
</activity>

The above code itself is self-explanatory. Your activity now can handle
intents that are launched with this signature. The action is “android.intent.action.ACTION_SEND
and the data scheme is “mailto”, i.e, any email address. So, in your
ComposeActivity, you can retrieve the email address list by querying the
intent for the key, EXTRA_EMAIL
and you will get the list of email addresses (one in this case).
Typically, you will need to populate the Send To address field of your
ComposeActivity now.

The intent resolution process tries to find a best match for the intent.
Once it finds an Intent and launches the Activity with or without user
interruption(in case multiple matches are found), the responsibility of
handling the intent now lies with the target component. To finish off
the article, here is the way to extract the email address that had been
clicked.

Bundle data = getIntent().getExtras();
String[] emailAddresses = data.get(Intent.EXTRA_EMAIL);

The developer docs
on Intent, Intent Filters and Intent Resolution mechanism is a nice
read to understand the Intent mechanism of Android. You can find other
examples of the types of data and schemes that you can design your apps
for.