Friday, August 3, 2012

Capture and Crop an Image with the Device Camera

,

Many Android devices are equipped with built-in cameras. In this tutorial, we will work through the basic technique for capturing an image using the Android camera and then cropping it using apps the user already has installed on their device. Along the way, I’ll also show how to account for users whose devices do not support either the image capture or cropping actions.

Step 1: Start a New Android Project

Create a new Android project in Eclipse, or your chosen IDE. In your main Activity class, add the following import statements after the package declaration:
1
2
3
4
5
6
7
8
9
10
11
12
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
These will allow us to carry out image capture, crop and display within the app. Open your application’s strings XML file, which you should find in the “res/values” folder. Add the following strings:
1
2
3
<string name="intro">Capture a picture to crop!</string>
<string name="picture">Picture</string>
<string name="capture">Launch Camera</string>
We will use these strings within the user interface.

Step 2: Implement the App Layout

Let’s design the app layout. Open your main XML file, which should be in the “res/layout” folder. Use a Linear Layout as follows, which Eclipse may have already provided:
1
2
3
4
5
6
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
</LinearLayout>
Inside the Linear Layout, add the following text display:
1
2
3
4
5
6
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/intro"
    android:layout_margin="3dp"
    android:textStyle="bold" />
Here we display some informative text using a string we defined in the strings XML file. After the Text View, add a button as follows:
1
2
3
4
5
<Button
    android:id="@+id/capture_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/capture" />
The ID value will allow us to identify the button in Java, so that we can respond to clicks. Again, we use a string we already defined in XML. Finally, after the button, add an Image View:
1
2
3
4
5
6
7
<ImageView
    android:id="@+id/picture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/picture"
    android:layout_margin="5dp"
    android:background="@drawable/pic_border" />
We will place the image captured by the user with their device camera inside this Image View, using the ID value to identify it in Java. We use one of the strings as a content description and a background drawable resource we will create next. If you want the Image View to stretch to fill the available space, alter the width and height attributes to “fill_parent” instead of “wrap_content” – remember that this may make the image displayed appear poor quality.
For the background drawable, create a new XML file in each of your app drawable folders, naming it “pic_border.xml” to match the value we used in the Image View layout section. The easiest way to do this is to create the file in one drawable folder, copy the XML code into it, save it, then copy it into the other drawable folders.
Use the following XML in your new “pic_border” drawable file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    android:dither="true">
    <gradient
        android:startColor="#99ffffff"
        android:endColor="#99ffffff"
        android:centerColor="#00000000"
        android:angle="90" />
    <padding android:left="10dp" android:top="10dp"
        android:right="10dp" android:bottom="10dp" />
    <corners android:radius="5dp" />
    <stroke
        android:width="2dp"
        android:color="#ccffffff" />
</shape>
Using a drawable background resource is entirely optional, so feel free to omit this part. This is how the app will look when it is launched:
Initial App Interface

Step 3: Respond to User Clicks

In your app’s Activity class, extend the opening class declaration line as follows:
1
public class ShootAndCropActivity extends Activity implements OnClickListener {
Alter the class name to suit your own. Inside the Activity “onCreate” method, add the following after the existing code calling the superclass method and setting the content layout, which Eclipse should have populated:
1
2
3
4
//retrieve a reference to the UI button
Button captureBtn = (Button)findViewById(R.id.capture_btn);
//handle button clicks
captureBtn.setOnClickListener(this);
Here we simply instruct the class to handle button clicks. The user will press the button to launch the camera. Now we need to provide an “onClick” method. Add it as follows, after the “onCreate” method:
1
2
3
4
5
public void onClick(View v) {
    if (v.getId() == R.id.capture_btn) {    
     
    }
}
Inside the “if” statement, we will implement using the camera.

Step 4: Launch the Camera

At the top of your class declaration, before the “onCreate” method, add the following instance variables:
1
2
3
4
//keep track of camera capture intent
final int CAMERA_CAPTURE = 1;
//captured picture uri
private Uri picUri;
We will use the first variable to keep track of the user’s interaction as they navigate to the camera app and back. The second variable will store the URI of the captured image. Inside the “if” statement in your “onClick” method, add the following code to launch the camera Intent, including it in a “try” block:
1
2
3
4
5
6
try {
    //use standard intent to capture an image
    Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //we will handle the returned data in onActivityResult
    startActivityForResult(captureIntent, CAMERA_CAPTURE);
}
When this code executes, the user’s camera app will start up and they will be able to take a photo. We will handle the user returning from the camera app inside the “onActivityResult” method. From there we will be able to check that the user is returning from this Intent using the “CAMERA_CAPTURE” variable we pass when starting the Activity. However, before we do that we need to handle the situation in which the user device does not support the image capture intent we have attempted to launch here. After the “try” block, add a “catch” as follows:
1
2
3
4
5
6
catch(ActivityNotFoundException anfe){
    //display an error message
    String errorMessage = "Whoops - your device doesn't support capturing images!";
    Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
    toast.show();
}      
Whenever you attempt to launch an Intent outside of your own app, this is a precaution you may wish to take. This is particularly the case with the cropping action which we will be exploring later, however this code pattern is a good habit to adopt in general, as user devices vary greatly. When the user accepts the photo they have captured, they will return to the app.
The Camera App

Step 5: Retrieve the Captured Image

We launched the camera app using “startActivityForResult” so we now need to handle the result. Add the “onActivityResult” method after the “onClick” method as follows:
1
2
3
4
5
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
         
    }
}
Inside the “if” statement, add another to check that we are returning from the camera app, using the variable we passed:
1
2
3
4
//user is returning from capturing an image using the camera
if(requestCode == CAMERA_CAPTURE){
             
}
We will also return to the “onActivityResult” method after the user crops their image, so we will add an “else if” later. Inside this “if” statement, add the following code to retrieve the URI of the captured photo:
1
2
//get the Uri for the captured image
picUri = data.getData();
Now we need to pass this URI to an app that can crop it. We will use a helper method to achieve this, so add the following method call:
1
2
//carry out the crop operation
performCrop();

Step 6: Crop the Captured Image

Add the helper method we called after the “onActivityResult” method:
1
2
3
private void performCrop(){
 
}
Inside this method we are going to call an Intent to perform the crop, so let’s add “try” and “catch” blocks in case the user device does not support the crop operation:
1
2
3
4
5
6
7
8
9
try {
 
}
catch(ActivityNotFoundException anfe){
    //display an error message
    String errorMessage = "Whoops - your device doesn't support the crop action!";
    Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
    toast.show();
}
We use the same technique we used when launching the camera Intent. If the user device does not support the cropping Intent, they will see an error message. Inside the “try” block, launch the Intent as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    //call the standard crop action intent (the user device may not support it)
Intent cropIntent = new Intent("com.android.camera.action.CROP");
    //indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
    //set crop properties
cropIntent.putExtra("crop", "true");
    //indicate aspect of desired crop
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
    //indicate output X and Y
cropIntent.putExtra("outputX", 256);
cropIntent.putExtra("outputY", 256);
    //retrieve data on return
cropIntent.putExtra("return-data", true);
    //start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, PIC_CROP); 
Here we set various properties for the cropped image, instructing the app to retrieve the resulting image data when the crop is complete. If you want the cropped image dimensions to differ from this, alter the “outputX” and “outputY” lines accordingly. We call the Intent using “startActivityForResult”, so will retrieve the result inside “onActivityResult” again. As with the camera Intent, we pass a variable to keep track of which Intent we are returning from, so add a variable declaration at the top of the class, next to the other instance variables:
1
2
//keep track of cropping intent
final int PIC_CROP = 2;
Image Cropping
As well as cropping, the user can select an area of the image.
Crop Detail

Step 7: Display the Cropped Image

Finally we can retrieve the cropped image and display it within the app UI. Inside your “onActivityResult” method, after the “if” statement in which you check for the “CAMERA_CAPTURE” request code, add an “if else” statement checking for the “PIC_CROP” code, in which case we are returning from the crop operation:
1
2
3
4
//user is returning from cropping the image
else if(requestCode == PIC_CROP){
 
}
Inside this statement, we can retrieve the returned cropped image as follows:
1
2
3
4
//get the returned data
Bundle extras = data.getExtras();
//get the cropped bitmap
Bitmap thePic = extras.getParcelable("data");
We now have the user’s cropped image as a Bitmap. Let’s display it in the Image View as follows:
1
2
3
4
//retrieve a reference to the ImageView
ImageView picView = (ImageView)findViewById(R.id.picture);
//display the returned cropped image
picView.setImageBitmap(thePic);
Now the cropped image will appear inside the app UI as soon as the user returns from cropping. Save and run your app on an actual device to test it.
Displaying the Image in the App

Conclusion

In this tutorial we have explored the basic capture and crop process within the Android SDK. However, the crop action in particular can be a little unpredictable on the various user devices in operation. Lots of different apps can handle the crop operation, so some developers adopt a more complex algorithm to resolve the user choices, presenting these apps to the user as a list of options to choose from. Whatever apps the user environment provides, the basic process of capture and crop remains the same.

(tutsplus)


Advanced Android: Getting Started with the NDK

,

Learn how to install the Android NDK and begin using it. By the end of this tutorial, you will have created your own project that makes a simple call from Java code to native C code.

Prerequisite Experience

Before we get started, we need to take a moment here to discuss the level of this tutorial. It’s flagged as advanced. The reason for this is that we, the authors, are going to assume that you would agree with the following statements:
  1. You are experienced with Java and C.
  2. You are comfortable using the command line.
  3. You know how to figure out what version of Cygwin, awk, and other tools you have.
  4. You are comfortable with Android Development.
  5. You have a working Android development environment (as if this writing, the authors are using Android 2.2)
  6. You use Eclipse or can translate Eclipse instructions to your own IDE with ease.
If you aren’t comfortable with these, you’re welcome to read this tutorial, of course, but you may have difficulties at certain steps that would be resolved by being comfortable with the above. That said, using the NDK is still a process that is prone to problems and issues even if you consider yourself a mobile development veteran. Be aware that you may have to do some troubleshooting of your own before you get everything working smoothly on your development system.
The complete sample project for this tutorial can be downloaded open source code.

A Note About When to Use NDK

So, if you’re reading this tutorial, you may already be considering the NDK for your Android projects. However, we’d like to take a moment to talk about why the NDK is important, when it should be used, and—just as importantly, when it should not be used.
Generally speaking, you only need to use the NDK if your application is truly processor bound. That is, you have algorithms that are using all of the processor within the DalvikVM and would benefit from running natively. Also, don’t forget that in Android 2.2, a JIT compiler will improve the performance of such code as well.
Another reason to use the NDK is for ease of porting. If you’ve got loads of C code for your existing application, using the NDK could speed up your project’s development process as well as help keep changes synchronized between your Android and non-Android projects. This can be particularly true of OpenGL ES applications written for other platforms.
Don’t assume you’ll increase your application’s performance just because you’re using native code. The Java<->Native C exchanges add some overhead, so it’s only really worthwhile if you’ve got some intensive processing to do.

Step 0: Downloading the Tools

Alright, let’s get started. You need to download the NDK. We’ll do this first, as while it’s downloading you can check to make sure you have the right versions of the rest of the tools you need.
Download the NDK for your operating system from the Android site.
Now, check the versions of your tools against these:
  1. If on Windows, Cygwin 1.7 or later
  2. Update awk to the most recent version (We’re using 20070501)
  3. GNU Make 3.81 or later (We’re using 3.81)
If any of these versions are too old, please update them before continuing.

Step 1: Installing the NDK

Now that the NDK is downloaded (it is, right?), you need to unzip it. Do so and place it in an appropriate directory. We put ours in the same directory that we put the Android SDK. Remember where you put it.
At this point, you may want to add the NDK tools to your path. If you’re on Mac or Linux, you can do this with your native path setting. If you’re on Windows using Cygwin, you need to configure the Cygwin path setting.

Step 2: Creating the Project

Create a regular Android project. To avoid problems later, your project must reside in a path that contains no spaces. Our project has a package name of “com.mamlambo.sample.ndk1” with a default Activity name of “AndroidNDK1SampleActivity” – you’ll see these appear again soon.
At the top level of this project, create a directory called “jni” – this is where you’ll put your native code. If you’re familiar with JNI, the Android NDK is heavily based on JNI concepts – it is, essentially, JNI with a limited set of headers for C compilation.

Step 3: Adding Some C Code

Now, within the jni folder, create a file called native.c. Place the following C code in this file to start; we’ll add another function later:
  1. #include <jni.h>  
  2. #include <string.h>  
  3. #include <android/log.h>  
  4.   
  5. #define DEBUG_TAG "NDK_AndroidNDK1SampleActivity"  
  6.   
  7. void Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_helloLog(JNIEnv * env, jobject this, jstring logThis)  
  8. {  
  9.     jboolean isCopy;  
  10.     const char * szLogThis = (*env)->GetStringUTFChars(env, logThis, &isCopy);  
  11.   
  12.     __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:LC: [%s]", szLogThis);  
  13.   
  14.     (*env)->ReleaseStringUTFChars(env, logThis, szLogThis);  
  15. }  

This function is actually fairly straightforward. It takes in a Java object String parameter, converts it in to a C-string, and then writes it out to LogCat.
The name of the function, though, is important. It follows the specific pattern of “Java,” followed by the package name, followed by the class name, followed by the method name, as defined from Java. Every piece is separated by an underscore instead of a dot.
The first two parameters of the function are critical, too. The first parameter is the JNI environment, frequently used with helper functions. The second parameter is the Java object that this function is a part of.

Step 4: Calling Native From Java

Now that you have written the native code, let’s switch back over to Java. In the default Activity, create a button and add a button handler however you want. From within your button handler, make the call to helloLog:
helloLog("This will log to LogCat via the native call.");  

Then you have to add the function declaration on the Java side. Add the following declaration to your Activity class:
private native void helloLog(String logThis);
This tells the compilation and linking system that the implementation for this method will be from the native code.
Finally, you need to load the library that the native code will ultimately compile to. Add the following static initializer to the Activity class to load the library by name (the library name itself is up to you, and will be referenced again in the next step):
  1. static {  
  2.     System.loadLibrary("ndk1");  
  3. }  

Step 5: Adding the Native Code Make File

Within the jni folder, you now need to add the makefile that will be used during compilation. This file must be named “Android.mk” and if you named your file native.c and your library ndk1, then the Android.mk contents will look like this:
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_LDLIBS := -llog  
  6.   
  7. LOCAL_MODULE    := ndk1  
  8. LOCAL_SRC_FILES := native.c  
  9.   
  10. include $(BUILD_SHARED_LIBRARY)  

Step 6: Compiling the Native Code

Now that your native code is written and your make file is in place, it’s time to compile the native code. From the command line (Windows users, you’ll want to do this within Cygwin), you’ll need to run the ndk-build command from the root directory of your project. The ndk-build tool is found within the NDK tools directory. We find it easiest to add this tool to our path.
Fig 1: Typical build output from the ndk-build command
On subsequent compiles, you can make sure everything is recompiled if you use the “ndk-build clean” command.

Step 7: Running the Code

Now you’re all set to run the code. Load the project in to your favorite emulator or handset, watch LogCat, and push the button.
One of two things may have happened. First, it may have worked. If so, congratulations! But you might want to read on, anyway. You probably got an error to LogCat saying something like, “Could not execute method of activity.” This is fine. It just means you missed a step. This is easy to do in Eclipse. Usually, Eclipse is configured to recompile automatically. What it doesn’t do is recompile and relink automatically if it doesn’t know anything has changed. And, in this case, what Eclipse doesn’t know is that you compiled the native code. So, force Eclipse to recompile by “cleaning” the project (Project->Clean from the Eclipse toolbar).

Step 8: Adding Another Native Function

This next function will demonstrate the ability to not only return values, but to return an object, such as a String. Add the following function to native.c:
  1. jstring Java_com_mamlambo_sample_ndk1_AndroidNDK1SampleActivity_getString(JNIEnv * env, jobject this, jint value1, jint value2)  
  2. {  
  3.     char *szFormat = "The sum of the two numbers is: %i";  
  4.     char *szResult;  
  5.   
  6.     // add the two values  
  7.     jlong sum = value1+value2;  
  8.   
  9.     // malloc room for the resulting string  
  10.     szResult = malloc(sizeof(szFormat) + 20);  
  11.   
  12.     // standard sprintf  
  13.     sprintf(szResult, szFormat, sum);  
  14.   
  15.     // get an object string  
  16.     jstring result = (*env)->NewStringUTF(env, szResult);  
  17.   
  18.     // cleanup   
  19.     free(szResult);  
  20.   
  21.     return result;  
  22. }  
For this to compile, you’ll want to add an include statement as well for stdio.h. And, to correspond to this new native function, add the following declaration in your Activity Java class:
  1. private native String getString(int value1, int value2);  
You can now wire up the functionality however you like. We used the following two calls and outputs:
  1. String result = getString(5,2);  
  2. Log.v(DEBUG_TAG, "Result: "+result);  
  3. result = getString(105, 1232);  
  4. Log.v(DEBUG_TAG, "Result2: "+result);  
Back to the C function, you’ll note that we did a couple things. First, we create need a buffer to write to for the sprintf() call using the malloc() function. This is reasonable so long as you don’t forget to free the results when you’re done using the free() function. Then, to pass the result back, you can use a JNI helper function called NewStringUTF(). This function basically it takes the C string and makes a new Java object out of it. This new String object can then be returned as the result and you’ll be able to use it as a regular Java String object from the Java class.
Fig 2: Screen from sample implementation

Instruction Sets, Compatibility, Etc.

The Android NDK requires Android SDK 1.5 or later. In later versions of the NDK, new headers have been made available for expanded access to certain APIs—in particular, OpenGL ES libraries.
However, that’s not the compatibility we’re talking about. This is native code, compiled to the processor architecture in use. So, one question you might be asking yourself is what processor architectures are supported? In the current NDK (as of this writing) only the ARMv5TE and ARMv7-A instruction sets are supported. By default, the target is set to ARMv5TE, which will work on all Android devices with ARM chips.
There are plans for further instruction sets (x86 has been mentioned). This has an interesting implication: an NDK solution will not work on all devices. For instance, there are Android tablets out there that use the Intel Atom processor, which has an x86 instruction set.
So how does the NDK work on the emulator? The emulator is running a true virtual machine, including full processor emulation. And yes, that means when running Java within the emulator you’re running a VM inside a VM.

Conclusion

How did you do? Did you get Android NDK installed and ultimately make a functional, running application that uses native C code as part of it? We hope so. There are many potential “gotchas!” along the way but in some cases, it can be worth the effort. As always, we’d love to hear your feedback.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams TeachYourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter@androidwireless.
tutsplus.com







Thursday, August 2, 2012

How to Install Android Apps to the SD Card by Default & Move Almost Any App to the SD Card

,


image
Android apps install to the internal storage by default, but you can also set the SD card as your default install location. This trick allows you to move almost any app to the SD card – no root access required.
This tweak requires Android 2.2 or later. To change the default install location, you’ll need to use the ADB, or Android Debug Bridge, utility included with Google’s Android SDK.

Enable USB Debugging

First, you’ll need to enable USB debugging on your Android device. Open the Settings screen, tap Applications, and select Development.

Tap the USB Debugging checkbox to enable it. This will enable debug mode, allowing you to change the settings on your Android device from your computer. You may want to disable debug mode after completing this process.

Install the Android SDK

You’ll need to download and install Google’s Android SDK on your computer. If you don’t already have Oracle’s Java JDK installed on your computer, you’ll have to download and install it before installing the Android SDK.
After you’ve installed both the JDK and Android SDK, launch the SDK Manager from your Start menu.

The ADB utility isn’t installed by default. It’s included in the Android SDK Platform-tools package – select this package and click the Install button to download and install it.

After the process completes, connect your Android device to your computer with its included USB cable. Windows should locate the device and install the appropriate drivers automatically. If it doesn’t, you may have to download and install the appropriate drivers from your Android device’s manufacturer. Do not mount the device after connecting it – just plug it in.

Using ADB

Open a Windows Explorer window and navigate to the android-sdk\platform-tools folder. On Windows, you’ll find this folder at C:\Program Files (x86)\Android\android-sdk\platform-tools by default. Check C:\Program Files\Android\android-sdk\platform-tools if you’re using a 32-bit version of Windows.

Launch a Command Prompt window in this folder by pressing and holding the Shift button, right-clicking in the folder, and selecting Open command window here.

Run the adb devices command and you should see your connected Android device.

Run the following command to set the default install location to your SD card:
adb shell pm setInstallLocation 2

If you want to revert this change later and install apps to the internal storage by default, run this command:
adb shell pm setInstallLocation 0
0 represents your device’s internal storage, and is the default. 2 represents the external storage, whether it’s an SD card or USB storage.

Moving Apps to SD Card

Apps that refused to leave your system storage can now be moved to the external storage. For instance, below you’ll see screenshots of the Slacker Radio app. Before the change was made, the Move to USB Storage button was grayed out. After the change was made, the button is enabled and the app can be moved.

To move an app to the SD card, open the Settings screen, tap Applications, and select Manage Applications. Select the app you want to move and tap the Move button on its details screen.

A Warning

Some apps shouldn’t be installed to your SD card and should remain installed on the internal storage. The external storage is unavailable when your Android device is mounted on your computer, so apps that remain running all the time should be left on your internal storage. Widgets, launchers, animated wallpapers, and anything you want to use while your Android’s SD card is mounted on your computer should be left on the internal storage.

(howtogeek)
 

Android Development Tutorials Copyright © 2011 -- Template created by O Pregador -- Powered by Blogger Templates