First, we want to create a UI so the user can create a Celebrity object that is stored to the API.
We will create a layout file called celebrity_layout.xml. and add the necessary UI components:
The code to accomplish this is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<EditText
android:id="@+id/firstNameEditText"
android:hint="First Name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:layout_marginLeft="25dip"
android:layout_marginRight="25dip">
<requestFocus />
</EditText>
<EditText
android:id="@+id/lastNameEditText"
android:hint="Last Name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:layout_marginLeft="25dip"
android:layout_marginRight="25dip"
android:layout_marginTop="5dip"
/>
<ImageButton
android:id="@+id/addCelebImageButton"
android:layout_width="150dip"
android:layout_height="225dip"
android:text="Add Celebrity"
android:src="@drawable/addphoto"
android:layout_marginTop="10dip"
android:onClick="selectImage"
/>
<Button
android:id="@+id/addCelebButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Celebrity"
android:layout_marginTop="10dip"
android:onClick="doneAction"
/>
</LinearLayout>
And the Activity should look like this:
We also have to add some resources for the tab appearance, to the appropriate res/drawable directories. Add the file icon_celebrity_tab.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_add_gr"
android:state_selected="true" />
<item android:drawable="@drawable/button_add_gray" />
</selector>
Next we create the CelebrityActivity. First, let's define the private data members:
private EditText m_firstNameEditText;
private EditText m_lastNameEditText;
private ImageButton m_addCelebImageButton;
private Celebrity m_celebrity;
private Uri m_imageCaptureUri;
private FatFractal ff = Hoodyoodoo.getFF();
private static final int PICK_FROM_CAMERA = 1;
private static final int PICK_FROM_FILE = 2;
Next, we create the methods we need in CelebrityActivity
In order to get the image for the Celebrity, we rely on the devices image library as populated from the camera, or from the browser. In our demo, we use the browser to save an image to the device and then select it with the very nice UIImagePickerController.
The selectImage method brings up the AlertDialog to select getting an image from the device using an Intent from either an Action of ACTION_GET_CONTENT or ACTION_IMAGE_CAPTURE depending upon if the user selects to capture from the device's camera or file system (if an image is stored, say from the browser to the device).:
public void selectImage(View v) {
final String [] items = new String [] {"From Camera", "From SD Card"};
ArrayAdapter adapter = new ArrayAdapter (this, android.R.layout.select_dialog_item,items);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select Image");
builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int item ) {
if (item == 0) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory(), "tmp_avatar_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
m_imageCaptureUri = Uri.fromFile(file);
try {
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, m_imageCaptureUri);
intent.putExtra("return-data", true);
startActivityForResult(intent, PICK_FROM_CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
dialog.cancel();
} else {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Complete action using"), PICK_FROM_FILE);
}
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
The onActivityResult: method will get the image, add it to the UIButton selectImageButton, clear the title and, most importantly, add the image data to the Celebrity object.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) return;
Bitmap bitmap = null;
String path = "";
if (requestCode == PICK_FROM_FILE) {
m_imageCaptureUri = data.getData();
String [] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(m_imageCaptureUri, proj, null, null, null);
if (cursor != null) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
path = cursor.getString(column_index);
if (path == null)
path = m_imageCaptureUri.getPath();
if (path != null)
bitmap = BitmapFactory.decodeFile(path);
}
} else {
path = m_imageCaptureUri.getPath();
bitmap= BitmapFactory.decodeFile(path);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
m_celebrity.setImageData(bitmapdata);
m_addCelebImageButton.setImageBitmap(bitmap);
}
Next, we add in the addGender method to get the gender information for the Celebrity using an AlertDialog and set the value for the Celebrity using the m_celebrity.setGender() method.
private void addGender() {
if(m_celebrity == null) m_celebrity = new Celebrity();
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setPositiveButton("Male", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
m_celebrity.setGender("male");
addCelebrity();
}
});
alert.setNegativeButton("Female", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
m_celebrity.setGender("female");
addCelebrity();
}
});
alert.show();
}
We use the doneAction method to check that the two EditText elements are not empty and then to set the Celebrity firstName and lastName values when the doneButton is clicked and then attempts to call addCelebrity.
public void doneAction(View view) {
if(m_celebrity == null) m_celebrity = new Celebrity();
if((m_firstNameEditText.getText().toString().length() >0) && (m_lastNameEditText.getText().toString().length() >0)) {
m_celebrity.setLastName(m_lastNameEditText.getText().toString());
m_celebrity.setFirstName(m_firstNameEditText.getText().toString());
addCelebrity();
}
}
Next, we add the addCelebrity method that:
public void addCelebrity() {
if(!ff.isLoggedIn()) {
Hoodyoodoo hoodyoodoo = new Hoodyoodoo();
AlertDialog alert = hoodyoodoo.loginDialog(this, "You must be logged in to save a new Celebrity.");
alert.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if(ff.isLoggedIn()) addCelebrity();
}
});
alert.show();
} else {
if((m_celebrity.getFirstName() == null) || (m_celebrity.getLastName() == null)) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Additional Information needed");
alert.setMessage("Please include a first and last name for the Celebrity");
alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();
}
else if(m_celebrity.getImageData() == null) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Additional Information needed");
alert.setMessage("Please include an image for the Celebrity");
alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
alert.show();
}
else if(m_celebrity.getGender() == null) {
addGender();
}
else {
try {
ff.createObjAtUri(m_celebrity, "/Celebrity");
m_celebrity = new Celebrity();
m_addCelebImageButton.setImageResource(R.drawable.addphoto);
m_firstNameEditText.setText(null);
m_lastNameEditText.setText(null);
} catch (FFException e) {
e.printStackTrace();
}
}
}
}
Now, make sure and connect up your UIComponents in the /res/layout/celebrity_layout.xml. To do this, we add the following to the onCreate method.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.celebrity_layout);
m_firstNameEditText = (EditText) findViewById(R.id.firstNameEditText);
m_lastNameEditText = (EditText) findViewById(R.id.lastNameEditText);
m_addCelebImageButton = (ImageButton) findViewById(R.id.addCelebImageButton);
m_celebrity = new Celebrity();
}
Finally, we need to declare our new Activity in AndroidManifest.xml. Add the following line to the application
element:
<activity android:name="com.hoodyoodoo.droidapp.activity.CelebrityActivity" />
That’s it! Now, we can select and image from the phone that was taken by the device camera or saved to the phone from the browser or other application, enter the first and last name, add the gender using the AlertDialog and the new Celebrity is stored to your API.
As mentioned previously, NoServer APIs can store any type of object, not just JSON or text. In this case, we have stored a Celebrity object that contains an image (byte[]) with a single method and can retrieve it the same way. And that is what we will do next.
Go ahead and add a few celebrities to you API as we will need them for the next section.
Final result - successfully added a Celebrity:
NEXT: Add WouldYaActivity