I'm taking emails from my Inbox folder with javamail api for my Android Application,
Is is possible to "just" have mail body with "content.toString()" ? If it's possible ,how can i view the mail body part by using adapters ? I tried SimpleAdapter and SimpleCursorAdapter but content is a type of Object, doesn't fit with the adapters.
What do you offer ?
Thanks.
private Message message;
private Object content;
message = inboxReader.inbox.getMessage(Integer.parseInt(_bundle.getString("RowId").toString()));
content = message.getContent();
Maybe you can try it
private static String getMailContent(Multipart multipart) throws IOException, MessagingException{
StringBuffer content = new StringBuffer();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
String disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equals(BodyPart.ATTACHMENT))) {
// ................................
} else {
content.append(bodyPart.getContent());
}
}
return content.toString();
}
Is this what you're looking for?
http://www.oracle.com/technetwork/java/javamail/faq/index.html#mainbody
Related
I am getting few google drive attachment links. I want to show them in the text view. But they should be appeared like Attachment 1, Attachment 2 - this way.
Attachment 1 will have a web link and attachment 2 will have another. They should be clickable.
I tried this way but it is not working:
mStrAttach = new ArrayList<>();
if(attchment_arr != null)
{
for(int i = 0; i < attchment_arr.length(); i++)
{
try
{
mStrAttach.add(attchment_arr.getString(i));
}
catch (JSONException e)
{
}
}
}
if(mStrAttach.size() > 0)
{
view.attchment.setText("");
for(int k = 0; k< mStrAttach.size(); k++)
{
String devid = mStrAttach.get(k);
Log.d("Testing", "drive id::: "+devid);
SpannableString ss = new SpannableString("Attachment "+""+(k+1));
ss.setSpan(new URLSpan(devid),0,ss.length(),0);
view.attchment.append(ss + "\n");
}
Linkify.addLinks(view.attchment, Linkify.ALL);
}
But it is not coming as a link. I am not able to click the Attachment 1 or 2.
Can someone please help.
Thanks,
Arindam.
You can save your attachement link in TextView Tag,
textview1.setTag(first_link);
textview2.setTag(second_link);
then whenever you want it just use textview1.getTag(), textview2.getTag();
I´m using Cordova-plugin-sms and it is working fine.
I can send sms except I cant exceed the standart 140-70 characters for each sms.
I need to send 2-in-1 sms like default SMS app.
For the exceeded size sms, it gives a successCallback, but sms is not sent.
https://github.com/floatinghotpot/cordova-plugin-sms
var successCallback = function () {
msgSentUser(message);
};
var failureCallback = function (e) {
};
SMS.sendSMS(number, fullMsg, successCallback, failureCallback);
Thank you,
Looking at the source code for that plugin, you can see that it uses the SmsManager#sendTextMessage() method. This method only handles single-part messages, and it will fail silently if you pass it a message that exceeds the character limit for a single part in the alphabet you're using. You still get the successCallback, however, since no Exception is thrown, and the plugin itself uses no other method of confirmation. The solution is to alter the code to utilize the sendMultipartTextMessage() method.
In the original source, lines 206 through 212, inclusive, handle the message send, and are what we need to replace. That is, these lines:
PendingIntent sentIntent = PendingIntent.getBroadcast((Context)this.cordova.getActivity(),
(int)0, (Intent)new Intent("SENDING_SMS"), (int)0);
SmsManager sms = SmsManager.getDefault();
for (int i = 0; i < n; ++i) {
String address;
if ((address = addressList.optString(i)).length() <= 0) continue;
sms.sendTextMessage(address, null, text, sentIntent, (PendingIntent)null);
}
The following replacement block divides the message into the appropriate parts, and creates the necessary ArrayList of PendingIntents to pass to the sendMultipartTextMessage() method. Please note that if you are handling the SENDING_SMS broadcast, it will now fire once for each message part, instead of once per send, as it did for single-part messages.
SmsManager sms = SmsManager.getDefault();
ArrayList<String> parts = sms.divideMessage(text);
final int count = parts.size();
ArrayList<PendingIntent> sentPIs = new ArrayList<PendingIntent>(count);
int req = 0;
PendingIntent pi = null;
for (int i = 0; i < n; i++) {
String address;
if ((address = addressList.optString(i)).length() <= 0) continue;
sentPIs.clear();
for (int j = 0; j < count; j++) {
req = i * count + j;
pi = PendingIntent.getBroadcast((Context) this.cordova.getActivity(),
req, new Intent("SENDING_SMS"), 0);
sentPIs.add(pi);
}
sms.sendMultipartTextMessage(address, null, parts, sentPIs, null);
}
The incoming message handling in that plugin is not correct, and will result in multipart messages appearing as multiple, separate messages. Two code sections will need to be altered to fix this. The first is lines 350 to 354, inclusive:
for (int i = 0; i < pdus.length; ++i) {
SmsMessage sms = SmsMessage.createFromPdu((byte[])((byte[])pdus[i]));
JSONObject json = SMSPlugin.this.getJsonFromSmsMessage(sms);
SMSPlugin.this.onSMSArrive(json);
}
Which we change to:
JSONObject json = SMSPlugin.this.getJsonFromSmsMessage(pdus);
SMSPlugin.this.onSMSArrive(json);
Next, we need to alter the getJsonFromSmsMessage() method; lines 447 through 466, inclusive:
private JSONObject getJsonFromSmsMessage(SmsMessage sms) {
JSONObject json = new JSONObject();
try {
json.put( ADDRESS, sms.getOriginatingAddress() );
json.put( BODY, sms.getMessageBody() );
json.put( DATE_SENT, sms.getTimestampMillis() );
json.put( DATE, System.currentTimeMillis() );
json.put( READ, MESSAGE_IS_NOT_READ );
json.put( SEEN, MESSAGE_IS_NOT_SEEN );
json.put( STATUS, sms.getStatus() );
json.put( TYPE, MESSAGE_TYPE_INBOX );
json.put( SERVICE_CENTER, sms.getServiceCenterAddress());
} catch ( Exception e ) {
e.printStackTrace();
}
return json;
}
This method will now be as follows. Please note that the method's parameter type has changed, and the JSONObject's value for the BODY key has, as well.
private JSONObject getJsonFromSmsMessage(Object[] pdus) {
SmsMessage sms = null;
StringBuilder sb = new StringBuilder();
JSONObject json = new JSONObject();
for (int i = 0; i < pdus.length; i++) {
sms = SmsMessage.createFromPdu((byte[]) pdus[i]);
sb.append(sms.getMessageBody());
}
try {
json.put(ADDRESS, sms.getOriginatingAddress());
json.put(BODY, sb.toString());
json.put(DATE_SENT, sms.getTimestampMillis());
json.put(DATE, System.currentTimeMillis());
json.put(READ, MESSAGE_IS_NOT_READ);
json.put(SEEN, MESSAGE_IS_NOT_SEEN);
json.put(STATUS, sms.getStatus());
json.put(TYPE, MESSAGE_TYPE_INBOX);
json.put(SERVICE_CENTER, sms.getServiceCenterAddress());
} catch (Exception e) {
e.printStackTrace();
}
return json;
}
For the sms concat i used this: ( i use this because 1 to 1 chat)
var totalSms = "";
function timeToAdd(newSms) {
totalSms = totalSms + newSms;
if (totalSms == newSms) { // only waits the first time
window.setTimeout(
function () {
msgReceived(totalSms);
addConversationMessage(totalSms, "sender");
totalSms = "";
}, 1000);
}
}
it basicly waits 1 second after the first "onsmsarrive" event to concat all the sms received (since every sms takes >1s to send) it should work
It seems like the problem is in:
safesmsExport.sendSMS = function(address, text, successCallback, failureCallback) {
var numbers;
if( Object.prototype.toString.call( address ) === '[object Array]' ) {
numbers = address;
} else if(typeof address === 'string') {
numbers = [ address ];
} else {
if(typeof failureCallback === 'function') {
failureCallback("require address, phone number as string, or array of string");
}
return;
}
cordova.exec(successCallback, failureCallback, 'SMS', 'sendSMS', [numbers, text]);
};
This is not calling the function sendSMS from the smsPlugin.java. Stands alone on SMS send even if smsPlugin sendSMS is commented.
I chose to change plugin. I got this one to work sending big sms: https://github.com/cordova-sms/cordova-sms-plugin , the problem is that this one doesn't have the startwatch. im trying to add it ( I'm new on plugins and JS as you can see)
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.
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 built an android app which can handle a share intent from Google Maps and show it's coordinates.
The problem is that they send a short url which I decode with Google's url shortner api and in some cases, the result long link is of this type: http://maps.google.com/?cid=3635533832900933072&hl=en&gl=us.
Can anyone help me on how to get the coresponding coordinates to "cid=3635533832900933072"
As far as I know there is no public API to get the location from a cid.
However, a possible workaround would be to parse the Google Maps output to obtain the latitude and longitude (though it may be brittle, if they change the result format).
(Although the url contains output=json, it's not actually json -- that's why I parse it with substring() and such instead of using JSONObject).
Try this code:
public static LatLng getCidCoordinates(String cid)
{
final String URL_FORMAT = "http://maps.google.com/maps?cid=%s&q=a&output=json";
final String LATLNG_BEFORE = "viewport:{center:{";
final String LATLNG_AFTER = "}";
final String LATLNG_SEPARATOR = ",";
final String LAT_PREFIX = "lat:";
final String LNG_PREFIX = "lng:";
try
{
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(String.format(URL_FORMAT, cid));
HttpResponse response = client.execute(get);
String text = EntityUtils.toString(response.getEntity(), "UTF-8");
int startIndex = text.indexOf(LATLNG_BEFORE);
if (startIndex == -1)
return null;
startIndex += LATLNG_BEFORE.length();
int endIndex = text.indexOf(LATLNG_AFTER, startIndex);
// Should be "lat:<number>,lng:<number>"
String[] parts = text.substring(startIndex, endIndex).split(LATLNG_SEPARATOR);
if (parts.length != 2)
return null;
if (parts[0].startsWith(LAT_PREFIX))
parts[0] = parts[0].substring(LAT_PREFIX.length());
else
return null;
if (parts[1].startsWith(LNG_PREFIX))
parts[1] = parts[1].substring(LNG_PREFIX.length());
else
return null;
return new LatLng(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]));
}
catch (NumberFormatException e)
{
e.printStackTrace();
return null;
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
After reading this post yesterday, I found a new method to do it. I hope Google do not close this new API and hidden parameter. :)
You can use this API hidden parameter to get the coordinater. Usage: https://maps.googleapis.com/maps/api/place/details/json?cid=YOUR_CID&key=YOUR_KEY
It returns a result contains formatted address, place_id, name of the address and GPS coordinater.
Please see my blog to see more detail: https://leonbbs.blogspot.com/2018/03/google-map-cid-to-placeid-or-get.html
In latest Google Maps update, the share intent contains the address name in the body which can be decoded with Geocoder into coordinates.