Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free triallyubendimitrov
2,093 PointsCan someone elaborate a bit more on how to send simple text?
I tried to add the option to send simple strings as the message instead of an image or video. I have added a button next to the camera in the Action Bar that starts a new Dialog with custom layout with an EditText and a button. Then I get the text from the EditText and via intent go to RecipientsActivity. But when I click on the send button I get an "IllegalArgumentException" : value may not be null;
Here is some code:
case R.id.action_message:
final Dialog messageDialog = new Dialog(this);
messageDialog.setContentView(R.layout.message_bar);
messageDialog.show();
Button messageButton = (Button)messageDialog.findViewById(R.id.send_button);
messageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText messageText = (EditText) messageDialog.findViewById(R.id.edit_text_message);
final String message = messageText.getText().toString();
if (TextUtils.isEmpty(message)) {
Toast.makeText(MainActivity.this, "Enter a message first!", Toast.LENGTH_SHORT).show();
} else {
Intent recipientsIntent = new Intent(MainActivity.this, RecipientsActivity.class);
recipientsIntent.putExtra(ParseConstants.TYPE_TEXT, message);
startActivity(recipientsIntent);
}
}
});
Do I need to adapt the RecipientsActivity to create the message in a different way if that message is not video or text? Perhaps some clues about the "mMediaUri" which in my case is empty as a text can't have that.
So yeah... just some directions of how to proceed will be nice :) Thanks!
5 Answers
Paul Stevens
4,125 PointsI have recently just done it for my Ribbit app. I will see if I can explain it here, I'm not very good yet so the code may not be the best, but it does work for me so far without problems.
First I added an icon to the action bar and changed the onOptionsItemSelected code in MainActivity to the following:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
switch(itemId) {
case R.id.action_logout:
ParseUser.logOut();
navigateToLogin();
break;
case R.id.action_edit_friends:
Intent intent = new Intent(this, EditFriendsActivity.class);
startActivity(intent);
break;
case R.id.action_camera:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(R.array.camera_choices, mDialogListener);
AlertDialog dialog = builder.create();
dialog.show();
break;
case R.id.action_message:
//*********************************************************
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Send Message.");
alert.setMessage("Type your message below.");
// Set an EditText view to get user input
final EditText input = new EditText(this);
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString();
Intent recipientsIntent = new Intent(MainActivity.this, RecipientsActivity.class);
recipientsIntent.putExtra(ParseConstants.KEY_MESSAGE, value);
recipientsIntent.putExtra(ParseConstants.KEY_FILE_TYPE, ParseConstants.TYPE_TEXT);
startActivity(recipientsIntent);
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();
//******************************************************
break;
}
Here is my code for the onListItemclick in the InboxFragment:
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ParseObject message = mMessages.get(position);
String messageType = message.getString(ParseConstants.KEY_FILE_TYPE);
String senderName = message.getString(ParseConstants.KEY_SENDER_NAME);
String displayMessage = message.getString(ParseConstants.KEY_MESSAGE);
ParseFile file = message.getParseFile(ParseConstants.KEY_FILE);
if (messageType.equals(ParseConstants.TYPE_IMAGE)) {
//view the image
Uri fileUri = Uri.parse(file.getUrl());
Intent intent = new Intent(getActivity(), ViewImageActivity.class);
intent.setData(fileUri);
startActivity(intent);
}else if (messageType.equals(ParseConstants.TYPE_VIDEO)){
Uri fileUri = Uri.parse(file.getUrl());
//view the video
Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
intent.setDataAndType(fileUri, "video/*");
startActivity(intent);
}else if (messageType.equals(ParseConstants.TYPE_TEXT)){
//Toast.makeText(getActivity(), displayMessage, Toast.LENGTH_LONG).show();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Message from: " + senderName + ".");
builder.setMessage(displayMessage);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
//delete the message
List<String> ids = message.getList(ParseConstants.KEY_RECIPIENT_IDS);
if(ids.size() == 1) {
//last recipient, delete the message
message.deleteInBackground();
}else {
//remove recipients name
ids.remove(ParseUser.getCurrentUser().getObjectId());
ArrayList<String> idsToRemove = new ArrayList<String>();
idsToRemove.add(ParseUser.getCurrentUser().getObjectId());
message.removeAll(ParseConstants.KEY_RECIPIENT_IDS, idsToRemove);
message.saveInBackground();
}
}
Here is my Parse Constants:
public final class ParseConstants {
//Class name
public static final String CLASS_MESSAGES = "Messages";
//Field names
public static final String KEY_USERNAME = "username";
public static final String KEY_FRIENDSRELATION = "friendsRelation";
public static final String KEY_RECIPIENT_IDS = "recipientIds";
public static final String KEY_SENDER_ID ="senderId";
public static final String KEY_SENDER_NAME ="senderName";
public static final String KEY_FILE ="file";
public static final String KEY_FILE_TYPE ="fileType";
public static final String KEY_CREATED_AT = "createdAt";
public static final String KEY_MESSAGE = "themessage";
public static final String TYPE_IMAGE ="image";
public static final String TYPE_VIDEO ="video";
public static final String TYPE_TEXT ="message";
}
My MessageAdapter :
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.message_item, null);
holder = new ViewHolder();
holder.iconImageView = (ImageView)convertView.findViewById(R.id.message_icon);
holder.nameLabel = (TextView)convertView.findViewById(R.id.sender_label);
convertView.setTag(holder);
}else {
holder = (ViewHolder)convertView.getTag();
}
ParseObject message =mMessages.get(position);
if (message.getString(ParseConstants.KEY_FILE_TYPE).equals(ParseConstants.TYPE_IMAGE)) {
holder.iconImageView.setImageResource(R.drawable.ic_action_picture);
}else if (message.getString(ParseConstants.KEY_FILE_TYPE).equals(ParseConstants.TYPE_VIDEO)){
holder.iconImageView.setImageResource(R.drawable.ic_action_play_over_video);
}else {
holder.iconImageView.setImageResource(R.drawable.ic_action_chat_light);
}
holder.nameLabel.setText(message.getString(ParseConstants.KEY_SENDER_NAME));
return convertView;
}
CreateMessage from RecipientsActivity:
protected ParseObject createMessage(){
ParseObject message = new ParseObject(ParseConstants.CLASS_MESSAGES);
message.put(ParseConstants.KEY_SENDER_ID, ParseUser.getCurrentUser().getObjectId());
message.put(ParseConstants.KEY_SENDER_NAME, ParseUser.getCurrentUser().getUsername());
message.put(ParseConstants.KEY_RECIPIENT_IDS, getRecipientIds());
message.put(ParseConstants.KEY_FILE_TYPE, mFileType);
//*************
if (mFileType.equals(ParseConstants.TYPE_TEXT)) {
message.put("themessage", mMyMessage);
message.put(ParseConstants.KEY_FILE_TYPE, "message");
return message;
}else{
//***************
byte[] fileBytes = FileHelper.getByteArrayFromFile(this, mMediaUri);
if (fileBytes == null) {
return null;
}else {
if(mFileType.equals(ParseConstants.TYPE_IMAGE)) {
fileBytes = FileHelper.reduceImageForUpload(fileBytes);
}
String fileName = FileHelper.getFileName(this, mMediaUri, mFileType);
ParseFile file = new ParseFile(fileName, fileBytes);
message.put(ParseConstants.KEY_FILE, file);
return message;
}
//***********
}
//***********
}
onCreate from RecipientsActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_recipients);
// Show the Up button in the action bar.
setupActionBar();
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mMediaUri = getIntent().getData();
mFileType = getIntent().getExtras().getString(ParseConstants.KEY_FILE_TYPE);
//***************
mMyMessage = getIntent().getExtras().getString("themessage");
//***************
}
I think these are all the changes I made, I kind of muddled through this so not sure if it's everything, but please feel free to ask if there is anything else I may be able to clarify. I have just pasted a lot of code with no explanations really, sorry, but I hope it helps a bit. :D
lyubendimitrov
2,093 PointsHey thanks for the help! I haven't finished the whole tutorial yet and I am not yet retrieving messages from Parse (just sending), so I don't need the MessageAdapter yet. But everything else seems perfect and does the job as you say!
I was missing something similar to the:
mMyMessage = getIntent().getExtras().getString("theMessage");
This is why it was complaining about IllegalArgumentException, but now it works.
Once again thanks!
Eric De Wildt
Courses Plus Student 13,077 PointsI am using this code but when I click on the edit text area it crashes the app.
adnanalvee2
6,862 PointsI had a quick question as I'm confused in the method where the Menu choices are in "onOptionsItemSelected(MenuItem item)"
if you see it is a switch statement with four cases or options as we see in the app, which are
**1. case R.id.action_logout:**
**2. case R.id.action_edit_friends:**
**3. case R.id.action_camera:**
**4. case R.id.action_message:**
Though I haven't done the extra credit for messages, my question is why does the "Logout" and "EditFriends" options stays together in a separate small window, and the camera button is outside in the actionbar. Arent they all supposed to be together side by side as that seems more logical with the switch statement code.
Anyone explain please?
Paul Stevens
4,125 PointsNo problem at all. Glad I could help. :)
Paul Stevens
4,125 PointsThat's strange Eric,
Can you post the error it gives you in the LogCat. Hopefully it can tell us what line of code the error is happening on.
Paul :)
Carlos Fernando Gómez Carrero
46,984 PointsHi Paul, sending a text message works very well with your code, thanks for sharing
Lend Kazazi
223 PointsI cannot see the text that i send because as soon as i touch the recieved text, the app crashes :(
Winthrop Granville
24,373 PointsPaul thanks for taking the time to post your code!
Lend - I had the same problem and it was because I was creating the Uri even if it was a text message. You only want to create the Uri if the message is an image or video message. So in InboxFragment you can simply move the below line to your if/else statements for the cases where the message is an image or video as Paul does in his code:
Uri fileUri = Uri.parse(file.getUrl());
lyubendimitrov
2,093 Pointslyubendimitrov
2,093 PointsI am getting near, but still struggling :(
Funny thing is I understand the way sending the images and videos work, but cannot adapt it for text - which should be trivia... I am trying to use the same way to upload the message as if it were image or video. Instead of calling startActivityForResult(), I am directly pointing to the RecipientsActivity with the message inside and a new TYPE_TEXT. So I guess now I have to handle that new "fileType" in RecipientsActivity when creating the message and omit the media URI. Perhaps put a new field to indicate text data is required as well? Any thoughts are welcome.
Ben Jakuben ? :)