So I've been using javamail API as part of my android app. After a login to a gmail account, the user can write new emails, check the inbox and sent mails. The emails are displayed in a listview with the help of an adapter class. (more accurately the sender, the subject and the sending date is displayed, and if the user clicks on the listview item, then the mail content will be displayed too on a new activity). All this is working well.
I would like to display unread emails differently (unread in the gmail client too), like set the textSyle bold if the mail is unread, but i'm having trouble adding this feature. I've been trying to check the flags of each fetched email message, but for some reason i dont see these flags in the variables.
My code snippet for fetching the mails (display is not here, that's in the adapter class):
protected ArrayList<Email_Message> doInBackground(Void... args) {
try {
Properties properties = new Properties();
properties.put("mail.store.protocol", "imaps");
Session emailSession = Session.getDefaultInstance(properties);
Store store = emailSession.getStore("imaps");
store.connect("imap.gmail.com", username, password);
// create the folder object and open it
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_WRITE);
Flags flags2 = emailFolder.getPermanentFlags(); //has 2 weird user flags in it ($phishing, $notphising) and systemflags = -2147483061 ???
Flags seen = new Flags(Flags.Flag.RECENT);
FlagTerm unseenFlagTerm = new FlagTerm(seen, false);
Message messages2[] = emailFolder.search(unseenFlagTerm); //this will net the same result as getMessages(), only here for testing
int test = emailFolder.getUnreadMessageCount(); //as far as i can tell this is working (i have 5000+ emails and 37 them are unread somewhere) but when i get a new email and the number goes up by 1 (38), and if i run the code again, after i already fetched the mails once, it's gonna be 37 again, and the mail marked as read in my gmail webclient too
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
int j = messages.length - 1;
for (int i = j - startIndex; i > j - startIndex - offset && i > (-1); i--) { //startIndex and offset are for displaying only 10 messages at the start and loading another 10 if the user scrolls to bottom
if (isCancelled()){
break;
}
Email_Message mailMessage = new Email_Message(); //my class for storing email messages
mailMessage.messageType = 1;
//some tricks to get the address in the right format
Address[] email_address = messages[i].getFrom();
String tempAddress = email_address[0].toString();
tempAddress = MimeUtility.decodeText(tempAddress);
//still tempering with address, not important
if(tempAddress.contains("=?")){
String[] AddressParts = tempAddress.split("\\?=");
mailMessage.messageAddress = AddressParts[1].substring(2);
}
else {
mailMessage.messageAddress = tempAddress;
}
Flags flags = messages[i].getFlags(); //user_flags = null, system_flags = 32
Flags.Flag[] systemflags = flags.getSystemFlags(); //has 1 item in it: bit = 32
String str[]= flags.getUserFlags(); //empty, these are all true for all my mails, not just one
mailMessage.messageDate = messages[i].getSentDate().toString();
mailMessage.messageSubject = messages[i].getSubject();
Object msgContent = messages[i].getContent();
String content = ""; //getting the content of the mail with these multipart stuffs
if (msgContent instanceof Multipart) {
Multipart multipart = (Multipart) msgContent;
Log.e("BodyPart", "MultiPartCount: " + multipart.getCount());
for (int k = 0; k < multipart.getCount(); k++) {
BodyPart bodyPart = multipart.getBodyPart(k);
String disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equalsIgnoreCase("ATTACHMENT"))) {
DataHandler handler = bodyPart.getDataHandler();
content = handler.getName();
} else {
content = bodyPart.getContent().toString();
}
}
} else
content = messages[i].getContent().toString();
mailMessage.messageContent = content;
EmailInbox.add(mailMessage);
}
// close the store and folder objects
emailFolder.close(false);
store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return EmailInbox;
}
I put some comments in the code to explain what i've found in the flags. What can I do to make this work? I already predict problems, like what happens after I read an unread mail in my app only, set its flag to seen, and when I start the activity again and fetch the mails, it's gonna be unread again, since I don't store them locally, but that's a problem after I managed to find a solution for this first.
Thanks for any help!
I'm not clear on how you're looking for the flags. Using messages[i].isSet(Flags.Flag.SEEN) will tell you if the SEEN flag has been set. Note that the SEEN flag will normally be set as soon as you access the content of the message, so you should not have to set it yourself.
Hint: use the InternetAddress.toUnicodeString method, or get the name and address separately using the getPersonal and getAddress methods. This will avoid any need to decode them yourself.
Related
I succeed login and post my wall.
FB.API("me/photos", Facebook.HttpMethod.POST, Callback, wwwForm);// it works well.
FB.Feed("", "link", "link_name", ~~bulabula~~ );// it works well, too!
//////////////AND PLEASE SEE NEXT CODE. THIS IS PROBLEM.///////////////////
private string FriendSelectorTitle = "Share it with your friends!";
private string FriendSelectorMessage = "invite";
private string FriendSelectorFilters = "[\"all\"]";
private string FriendSelectorData = "{data}";
private string FriendSelectorExcludeIds = "";
private string FriendSelectorMax = "5";
private void CallAppRequestAsFriendSelector()
{
// If there's a Max Recipients specified, include it
int? maxRecipients = null;
if (FriendSelectorMax != "")
{
try
{
maxRecipients = Int32.Parse(FriendSelectorMax);
}
catch (Exception e)
{
//status = e.Message;
Debug.Log(e.Message);
}
}
// include the exclude ids
string[] excludeIds = (FriendSelectorExcludeIds == "") ? null : FriendSelectorExcludeIds.Split(',');
List<object> FriendSelectorFiltersArr = null;
if (!String.IsNullOrEmpty(FriendSelectorFilters))
{
try
{
FriendSelectorFiltersArr = Facebook.MiniJSON.Json.Deserialize(FriendSelectorFilters) as List<object>;
}
catch
{
throw new Exception("JSON Parse error");
}
}
FB.AppRequest(
FriendSelectorMessage,
null,
FriendSelectorFiltersArr,
excludeIds,
maxRecipients,
FriendSelectorData,
FriendSelectorTitle,
Callback
);
}
void Callback(FBResult result)
{
Debug.Log(result.Text);
}
/////////////////////////////////////////////////
it look like works well.
first, pop up friends selector dialog,
and I clicked some friends, and click 'done' button.
it will call 'Callback' Funtion, and
debug.log(FBResult.text); show follow like this.
{"request":"8939391818800568","to":["2446462595631736"],["189238719238719238"]}
but now, I don't know how to use these values. T_T
I think FB.feed(); is well done. So,
I try to
for( int i=0; i<usernum; i++ )
{
FB.feed( "id[user_index]" , bula~bula );
}
but failed.
becuase, fbresult.text is not string!!?
I try to split this string(fbresult.text), to get "to":["userid1 number"], ["userid2 number"]
but I failed and disappointed.
please someone help me.
Anybody who has a good idea???
I really want to send my message(pic or message) to friend's facebook wall.
You canĀ“t post to the wall of a friend anymore, since a very long time. In most (all?) cases this would be considered as spam, so they remove that possibility.
You can use the Send Dialog to send something to a friend, for example.
I need to get followers list of currently logged in user. I saw this but how to make the URL request and manage the result. Can I make normal network request by using volley or something ? Any help is appreciated.
I was also facing the same problem. Then I found java wrapper for this functionality Twitter4j. It is very easy to use. Following are the lines of code which I use for storing followers ids in a list.
List<Long> ids = new ArrayList<Long>();
twitter4j.Twitter twitter1;
ConfigurationBuilder config =
new ConfigurationBuilder()
.setOAuthConsumerKey(custkey)
.setOAuthConsumerSecret(custsecret)
.setOAuthAccessToken(accesstoken)
.setOAuthAccessTokenSecret(accesssecret);
twitter1 = new TwitterFactory(config.build()).getInstance();
while(cursor != 0 && length > 0) {
System.out.println("in loop");
try {
IDs temp = twitter1.friendsFollowers().getFollowersIDs(username, cursor);
cursor = temp.getNextCursor();
tempids = temp.getIDs();
length = temp.getIDs().length;
} catch (twitter4j.TwitterException e) {
e.printStackTrace();
}
for (long id : tempids) {
ids.add(id);
}
}`
I also asked the same question in Twitter community. You can check it out at
https://twittercommunity.com/t/get-followers-of-a-user-using-twitter-android-sdk/37740
I created an android app to show comments of certain post from facebook.
what I want to do is to implement the like button.
I have all the necessary data (facebook token, user id, app id etc.) and permission i need from the user.
circle number 1 is the content of the comment
circle number 2 is the name if the user
circle number 3 is the like button that i want to implement
circle number 4 is the time that the comment sent
I use this link to get the comments:
https://graph.facebook.com/568609876496765/comments
it returns a JSON Object that i phrase and get the data and show it in a List View.
Thanks in advance.
Unlike webpages, you cannot add a Facebook Like button to an Android app. However, you can add the function to Like a post (a Comment in your case) by using "POST" or a "DELETE" query to the Facebook API:
Here is a complete functioning example of what I do to Toggle the Like Status of a Comment in my application:
NOTE: This code is for the older v2.x SDK. So you will need to adapt a few things that are specific to the latest v3.x SDK
On the onClickListener you will use to post / remove a Like, run this piece of code:
try {
String query = "SELECT user_likes FROM comment WHERE post_id= \'"
+ THE_COMMENT_ID + "\'";
Bundle params = new Bundle();
params.putString("method", "fql.query");
params.putString("query", query);
String fqlResponse = Utility.mFacebook.request(params);
JSONArray JALikes = new JSONArray(fqlResponse);
for (int j = 0; j < JALikes.length(); j++) {
JSONObject JOTemp = JALikes.getJSONObject(j);
if (JOTemp.has("user_likes")) {
String userLikeStatus = JOTemp.getString("user_likes");
if (userLikeStatus.equals("true")) {
try {
Bundle parameters = new Bundle();
Utility.mFacebook.request(arrayComments.get(position).getCommentID() + "/likes", parameters, "DELETE");
// CHANGE THE TEXT OF THE WIDGET TO SHOW THE TOGGLED STATE
}
catch(Exception e) {
e.printStackTrace();
}
} else if (userLikeStatus.equals("false")) {
try {
Bundle parameters = new Bundle();
Utility.mFacebook.request(arrayComments.get(position).getCommentID() + "/likes", parameters, "POST");
// CHANGE THE TEXT OF THE WIDGET TO SHOW THE TOGGLED STATE
}
catch(Exception e) {
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
In the first part of the code (before the for loop), I check the current status if the Logged in user likes the Comment. Based on the result (in the for loop), I either remove the Like or I post a Like.
Although it is an older SDK, the code is still valid, and with a few modifications (if necessary) will work just fine.
I'm trying to get the user's cover photo and show it at the top of a layout. I'm using AsyncTask to run the API call to Facebook. The code I'm using to get the Facebook data is
JSONObject json = null;
response = Utility.facebook.request("me?fields=cover");
json = Util.parseJson(response);
The exception that stops the thread comes from a json error on the next step because the returned json is empty, even though the request clears through. I can get a proper json using just "me" or "me/albums" or anything other than "me?fields=cover". When I comment out the last line, 'try' process finishes with no exceptions/errors.
Is there something wrong with the Facebook API or am I doing something wrong?
I personally prefer using FQL when dealing with User Profile. If you would like to give FQL a try, check the following piece of code. If you would like to stick to Graph API, see this answer: https://stackoverflow.com/a/12434640/450534
try {
String query = "SELECT pic_cover FROM user where uid = " + PUT_THE_USER_ID_HERE;
Bundle param = new Bundle();
param.putString("method", "fql.query");
param.putString("query", query);
String response = Utility.mFacebook.request(param);
JSONArray JAUser = new JSONArray(response);
for (int i = 0; i < JAUser.length(); i++) {
JSONObject JOUser = JAUser.getJSONObject(i);
// COVER PHOTO
if (JOUser.has("pic_cover")) {
String getCover = JOUser.getString("pic_cover");
if (getCover.equals("null")) {
String finalCover = null;
} else {
JSONObject JOCoverSource = JOUser.optJSONObject("pic_cover");
if (JOCoverSource.has("source")) {
String finalCover = JOCoverSource.getString("source");
} else {
String finalCover = null;
}
}
} else {
String finalCover = null;
}
}
} catch (Exception e) {
// TODO: handle exception
}
The above code already accounts for User's who do not have a Cover Photo set in their profiles and checks for its availability. With this code, you will have the URL to the Cover Photo and can then process it as you prefer.
NOTE: If you are fetching the logged in users cover photo, this piece of code SELECT pic_cover FROM user where uid = " + PUT_THE_USER_ID_HERE; can also be written as: SELECT pic_cover FROM user where uid = me()"; For the non-logged in user's cover photo, the above can be used as is.
Couple of things as a side note.
I use Fedor's Lazy Loading technique to load images in almost exclusively.
I recommend running the code block, mine or any other solution you choose, in an AsyncTask.
The reason for not getting any result can be found in the javadoc of request(String graphPath) method:
(...) this method blocks waiting for a network response, so do not
call it in a UI thread.
In your case, you should probably do the following synchronous call:
Bundle params = new Bundle();
params.putString("fields", "cover");
String result = Utility.facebook.request("me/", params);
Siddharth Lele is very correct in his answer, but I wanted to specify the actual reason for not getting any response in this case.
Note: Fetching Cover Photo using Facebook API and endpoint https://graph.facebook.com/me?fields=cover no longer works as on 20th Dec 2014.
It was supposed to give following response:
{
"cover": {
"cover_id": "10151008748223553",
"source": "http://sphotos-a.ak.fbcdn.net/hphotos-ak-ash4/s720x720/391237_10151008748223553_422785532_n.jpg",
"offset_y": 0
},
"id": "19292868552"
}
But now it just gives User's id:
{
"id": "19292868552"
}
Verified this using Graph Tool explorer v2.2 using me?fields=cover.
I am doing on task to retrieve gmails. I manage to retrieve with below codes. However, it retrieved received email from the earliest to latest emails in the gmail inbox. Is there a way to make it retrieved the latest mails? I intend to implement a way to retrieved the latest 20 mails only instead of retrieved all the mails in the inbox. Thanks in advance for the guidance.
public ArrayList<HashMap<String, String>> getMail(int inboxList){
Folder inbox;
/* Set the mail properties */
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
try
{
/* Create the session and get the store for read the mail. */
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com",username, password);
/* Mention the folder name which you want to read. */
inbox = store.getFolder("Inbox");
System.out.println("No of Unread Messages : " + inbox.getUnreadMessageCount());
/*Open the inbox using store.*/
inbox.open(Folder.READ_WRITE);
/* Get the messages which is unread in the Inbox*/
Message messages[];
if(recent){
messages = inbox.search(new FlagTerm(new Flags(Flag.RECENT), false));
}else{
messages = inbox.search(new FlagTerm(new Flags(Flag.SEEN), false));
}
/* Use a suitable FetchProfile */
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.ENVELOPE);
fp.add(FetchProfile.Item.CONTENT_INFO);
inbox.fetch(messages, fp);
try
{
printAllMessages(messages);
inbox.close(true);
store.close();
}
catch (Exception ex)
{
System.out.println("Exception arise at the time of read mail");
ex.printStackTrace();
}
}
catch (NoSuchProviderException e)
{
//e.printStackTrace();
System.exit(1);
}
catch (MessagingException e)
{
//e.printStackTrace();
System.exit(2);
}
Instead of using inbox.search() use
inbox.getMessages(int start,int end);
it will retrieve the range of messages.
To get the latest 20 mails use:
int n=inbox.getMessageCount();
messages= inbox.getMessages(n-20,n);
If you just want the last 20 messages, just ask for the last 20 message numbers,
or access the last 20 entries in the array returned by folder.getMessages().
Not that the order of messages in the mailbox is the order in which they arrived,
not the order in which they were sent.
Used the android.os.Message
static class DateCompare implements Comparator<Message> {
public int compare(Message one, Message two){
return one.getWhen().compareTo(two.getWhen());
}
}
............
DateCompare compare = new DateCompare();
Message messages[];
if(recent){
messages = inbox.search(new FlagTerm(new Flags(Flag.RECENT), false));
}else{
messages = inbox.search(new FlagTerm(new Flags(Flag.SEEN), false));
}
List<Message> list = Arrays.asList(messages );
Collections.sort(list,compare);
List<Messsage> newList = list.subList(0,19);
hope this helps.