Category Archives: Android

3D Flip Between Two View or ViewGroup on Android

3D flip makes a nice effect. It seems like there is no good android implementation on the internet that shows how to make two generic view flip with each other. Let me first show you the end result, the card flips if you clicking on it anywhere.

First the activity layout file:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_activity_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/transparent" >

<RelativeLayout
android:id="@+id/main_activity_card_face"
android:layout_width="300dp"
android:layout_height="407dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/front"
android:clickable="true"
android:onClick="onCardClick"
android:padding="5dp" >
</RelativeLayout>

<RelativeLayout
android:id="@+id/main_activity_card_back"
android:layout_width="300dp"
android:layout_height="407dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/back"
android:clickable="true"
android:onClick="onCardClick"
android:visibility="gone" >
</RelativeLayout>

</RelativeLayout>

As the layout file flips two view groups you could put anything else inside the view group and it should work. Now lets look at the methods inside the activity which handles calling the flip animation code:

public void onCardClick(View view)
{
      flipCard();
}

private void flipCard()
{
	View rootLayout = (View) findViewById(R.id.main_activity_root);
	View cardFace = (View) findViewById(R.id.main_activity_card_face);
	View cardBack = (View) findViewById(R.id.main_activity_card_back);

	FlipAnimation flipAnimation = new FlipAnimation(cardFace, cardBack);

	if (cardFace.getVisibility() == View.GONE)
	{
		flipAnimation.reverse();
	}
	rootLayout.startAnimation(flipAnimation);
}

And finally the FlipAnimation class:

public class FlipAnimation extends Animation
{
    private Camera camera;

    private View fromView;
    private View toView;

    private float centerX;
    private float centerY;

    private boolean forward = true;

    /**
     * Creates a 3D flip animation between two views.
     *
     * @param fromView First view in the transition.
     * @param toView Second view in the transition.
     */
	public FlipAnimation(View fromView, View toView)
    {
        this.fromView = fromView;
        this.toView = toView;

		setDuration(700);
        setFillAfter(false);
        setInterpolator(new AccelerateDecelerateInterpolator());
    }

    public void reverse()
    {
        forward = false;
		View switchView = toView;
        toView = fromView;
        fromView = switchView;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight)
    {
        super.initialize(width, height, parentWidth, parentHeight);
        centerX = width/2;
        centerY = height/2;
        camera = new Camera();
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t)
    {
        // Angle around the y-axis of the rotation at the given time
        // calculated both in radians and degrees.
        final double radians = Math.PI * interpolatedTime;
        float degrees = (float) (180.0 * radians / Math.PI);

        // Once we reach the midpoint in the animation, we need to hide the
        // source view and show the destination view. We also need to change
        // the angle by 180 degrees so that the destination does not come in
        // flipped around
        if (interpolatedTime >= 0.5f)
        {
            degrees -= 180.f;
            fromView.setVisibility(View.GONE);
            toView.setVisibility(View.VISIBLE);
        }

        if (forward)
            degrees = -degrees; //determines direction of rotation when flip begins

        final Matrix matrix = t.getMatrix();
        camera.save();
        camera.rotateY(degrees);
        camera.getMatrix(matrix);
        camera.restore();
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }

The FlipAnimation code was borrowed from code I found somewhere on internet. I can’t find reference to it anymore so if anyone happens to find anything similar please provide reference in the comments and I’ll link it up. The images I used in the code you can grab similar images from here.

Try modifying the code and making a flip around X axis and if you read this far consider following me on Twitter:

Advertisements

Checking Type of Internet Connection Wifi/Mobile

There are primarily two ways of connecting to internet in android. It can be either wifi or 3G (mobile data connection). If its a wifi connection and the application wants the wifi connection to stay active while the device goes to sleep then acquire a wifi lock and release it when the application is finished with internet related work otherwise the application will lose connectivity after devices goes to sleep. On the other hand 3G does not requires any type of lock to stay awake. A code can inquire about the type of network a device is connected to using following piece of code:

ConnectivityManager conManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiInfo = conManager.getNetworkInfo((ConnectivityManager.TYPE_WIFI));
NetworkInfo mobileInfo = conManager.getNetworkInfo((ConnectivityManager.TYPE_MOBILE));

if (wifiInfo.isConnectedOrConnecting() )
{
       Log.v("NetworkState", "Connected or connecting to wifi");
}
else if (mobileInfo.isConnectedOrConnecting())
{
       Log.v("NetworkState", "Connected or connecting to mobile data connection");
}

Add the following permission to the application AndroidManifest.xml otherwise the application will throw a run time exception:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Registering for Broadcast through AndroidManifest

Here is a small tip that took me a while to figure out but hopefully will save someone time and frustration. I have a BroadcastReceiver in my application that listens for network connectivity changes so the app. can resume background work on network availability.

If you register for receiver in AndroidManifest.xml then you need to write the actual constant value inside the <intent-filter> tag:

<intent-filter>
       <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>

The value is for the intent constant ConnectivityManager.CONNECTIVITY_ACTION. There are no warning or exceptions if you put this constant variable straight away in AndroidManifest.xml but the receiver won’t catch the network change events so a little hard to debug.

Note that if you register for a broadcast receiver from within code then just referring to the constant will work fine.

Checking your app. against Android Market technical filters

As android is designed to run on many different type of devices so an app has to be designed such that it is able to cope variety of devices with different hardware. I been working on an android app which uses internet so its not a must to have wifi for the device as it could just as well connect with 3G. I wanted to be sure that the app will be available for devices that might not have wifi but still could connect using 3G. This can be configured through the <uses-feature> tag in the application AndroidManifest.xml:

<uses-feature android:name="android.hardware.wifi" android:required="false" />

What android market does is that it filters the applications for a device so that users see and download only those applications which are compatible with their device. The market filtering is based on explicit and implicit features of an application and it is implemented in part by the aapt tool. A developer can check against this filtering by the following command:

$ aapt dump badging <path_to_exported_.apk>

The tool will return you a lot of other information such as what screen size and density an application is compatible with, what language it supports etc. The aapt tool can be found under SDK Install Dir/platforms/android-x/tools or SDK Install Dir/platform-tools

Here is the output by the above command for my application:

package: name=’guestshots.activities’ versionCode=’1′ versionName=’1.0′
sdkVersion:’7′
uses-permission:’android.permission.INTERNET’
uses-permission:’android.permission.WAKE_LOCK’
uses-permission:’android.permission.ACCESS_NETWORK_STATE’
uses-permission:’android.permission.ACCESS_WIFI_STATE’
uses-feature-not-required:’android.hardware.wifi’
application: label=’GuestShots’ icon=’res/drawable-mdpi/logo.png’
launchable activity name=’guestshots.activities.AccountSetup’label=’GuestShots’ icon=”
uses-feature:’android.hardware.touchscreen’
main
other-activities
other-receivers
other-services
supports-screens: ‘small’ ‘normal’ ‘large’
supports-any-density: ‘true’
locales: ‘–_–‘
densities: ‘120’ ‘160’ ‘240’

So looking at this output I’m 100% sure that my app. doesn’t force the wifi requirement and will be available for all three density and screen size devices and that a device need to have touch screen in order to use my application.

Working with Android SD Cards image on Mac

I wanted to load images (could be some other media file for that matter) into an sd card and connect that sd card image with the an android emulator. The post by Jayway team (http://blog.jayway.com/2009/04/22/working-with-sd-cards-in-the-android-emulator/) helped me to get started but those instructions are linux specific and didn’t work for me on mac. In the end it turned out pretty simple. So here is what I did:

Go to SDK Install Dir/tools folder:

./mksdcard 128M sdcard1.iso

Now clicking the .iso file mac would automatically load it in Finder. Thanks to Jayway post I created a directory /dcim/Camera in the loaded iso file and dragged couple of images into this directory.

From here onwards you have couple of options:

1. Create an android virtual device (avd) using the android SDK Manager or android command line tool, whichever you prefer, and specify the path to the sd image file (sdcard1.iso). To shoot up the GUI utility just type ./android inĀ SDK Install Dir/tools folder. For command line utility refer here: http://developer.android.com/guide/developing/tools/avd.html

To use an existing avd:

2. emulator -avd my_android1.5 -sdcard sdcard1.iso

And there you go you should be able to see the images in Android Gallery application.