Create a new project in Android Studio. Name your Activity NewMessageActivity.
We will now create a label for the message sender input field. Go to the layout file (activity_new_message.xml) and add TextView component inside the root LinearLayout. Give it a width of wrap_content (as wide as the text inside it plus paddings etc.) and height of wrap_content (will be as big as the text content plus paddings etc.). To show the label text, add the android:text attribute and refer to a string in the res/values/strings.xml file by using the syntax @string/your_string. You will need to create this string in the strings resource file.
Create the input field for message sender by adding an EditText component inside the root LinearLayout. Give it a width of match_parent (fill the screen from left to right) and height of wrap_content. To be able to access the input text in the activity, we need to give the edittext an android:id attribute. We will use a special syntax when creating this id for the first time: @+id/your_id. Later on, if you need to refer to this component you can skip the + sign.
Repeat the two above steps for creating a label and input field for the message text.
Add a button component for sending the message. Give it wrap_content for width and height. Give it an id. Give it the text "send" (use the strings.xml file).
By now, you should have two pairs of TextView and EditText and a send button, and the EditTexts and the button should each have an id. To test your app, Android needs to know which activity to launch when your app is started. To do this you must make sure your activity is registered in the manifest file and that an intent filter with action MAIN and category LAUNCHER is specified. Then start your app by clicking Run -> Debug and select "Launch emulator".
To send the message we need to respond to pressing the send button. Go to NewMessageActivity and inside the onCreate method, use the activity method View findViewById(int id) to get a reference to the button. The id will be available on the global R object by R.id.your_button_id. Do the same with the sender and message EditText. Remember to cast the generic views to EditText and Button. Use setOnClickListener on the button and inside the onClick callback you can get the text of the sender and message by using getText().toString() on the instances. To test everything, display a Toast message with the sender and message, and test using the emulator/device.
1b. Sending new messages to the API
Create a MessageApi interface using Retrofit with a send operation that accepts a sender and a message.
Use a Singleton to obtain an instance in your activity of the MessageApi using a Retrofit object. See example in the wiki chapter "Consume REST APIs with Retrofit". Use the base url http://mobile-course.herokuapp.com/.
Call your send operation in the click listener where you previously displayed a toast.
Test that sending works by opening http://mobile-course.herokuapp.com/ in a browser
2. Displaying the messages
Create a MessagesActivity and corresponding layout. Add a RecyclerView to the layout and get a reference to it in the activity.
compile 'com.android.support:recyclerview-v7:+'
Create a layout file for displaying messages in the list, f. ex /res/layout/item_message.xml, and put in some views to display the message sender, text and date.
Create a MessagesAdapter class that extends RecyclerView.Adapter and implement the required methods.
Use Retrofit to create a client for the REST API and fetch the messages asynchronously.
Add the received messages to the adapter and notify it of the changed message list.
Hints
The ViewHolder you create should contain references to all the TextViews you need to show for each position in the message list.
You will need a LayoutInflater in MessagesAdapter in onCreateViewHolder to create the layout view of the message. It is probably easiest to use Activitys getLayoutInflater() and pass it to the adapter.
Store a reference to the list of messages in MessagesAdapter. When you have added some messages to the list, call notifyDataSetChanged on the adapter, and it will render the messages again.
3. Show images
Add an ImageView in your message layout (e.g. item_message.xml).
In onBindViewHolder in MessagesAdapter, use the Picasso image loader library to load the image from a url if it exists for that message.
Hints
Add the Picasso dependency to your app.gradle file: compile 'com.squareup.picasso:picasso:2.5.2'.
4. Use the camera to add images to your messages
Add a button in your new message layout and add an OnClickListener for it in NewMessageActivity.
In the listener, start the image capture by using an Intent.
Override onActivityResult(...) to receive to captured photo.
Use the provided ImgurUpload class to upload the photo to Imgur.
Set the imgur url on the message and post it as before.
Create a file to store the captured photo
Use getExternalFilesDir(Environment.DIRECTORY_PICTURES) to get a directory where you can create a file for storing the captured photo.
Create an intent to start the camera
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT,imageFileUri);intREQUEST_IMAGE_CAPTURE=0;// Some constantstartActivityForResult(intent,REQUEST_IMAGE_CAPTURE);
Receive the captured photo
@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){if(requestCode==REQUEST_IMAGE_CAPTURE&&resultCode==RESULT_OK){BitmapFactory.OptionsbmpFactoryOptions=newBitmapFactory.Options();bmpFactoryOptions.inJustDecodeBounds=false;BitmapFactory.decodeFile(imageFile.getPath(),bmpFactoryOptions);bmpFactoryOptions=newBitmapFactory.Options();intinSampleSize=4;// Scale the image to a quarter of the original sizebmpFactoryOptions.inSampleSize=inSampleSize;BitmapscaledBitmap=BitmapFactory.decodeFile(imageFile.getPath(),bmpFactoryOptions);// Upload bitmap to Imgur}}
5. Improve the design or implement more API operations. Choose 5a or 5b.
5a. Improve design
Use a android.support.v7.widget.CardView in the item_message layout and make it look good.
Add a Lollipop toolbar to your app by using the support library (android.support.v7.widget.Toolbar). Put it in a separate layout file so that you can include it in all activities. Style it with a theme.
Use com.amulyakhare:com.amulyakhare.textdrawable to display a colored box for each message with the first letter of recipients name, ala. Gmail. Use ColorGenerator with material design colors.
By using the library com.github.shell-software:fab, add a FAB button (again, like Gmail) for creating a new message.
5b. Edit and delete messages
Add an EditMessageActivity. Try to reuse the layout for NewMessageActivity as much as you can.
Implement delete. You can f. ex have add a delete button in EditMessageActivity or delete by long-pressing messages in the list.
Hints
To pass objects between activities in intents, you can serialize them using Gson, and pass the serialized string instead. Convert back from json to java at the destination activity.
If you want to use retrofit, you will need to add a gradle dependency. The follow versions of Retrofit and the Gson converter
were used when creating this workshop: