Android Open Source - android_sms_backup Cursor To Message






From Project

Back to project page android_sms_backup.

License

The source code is released under:

Apache License

If you think the Android project android_sms_backup listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright (c) 2009 Christoph Studer <chstuder@gmail.com>
 */*from   w  ww. j a v  a  2s  .  c  om*/
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package tv.studer.smssync;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Contacts.ContactMethods;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
import android.util.Log;

import com.android.email.mail.Address;
import com.android.email.mail.Flag;
import com.android.email.mail.Message;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Message.RecipientType;
import com.android.email.mail.internet.MimeMessage;
import com.android.email.mail.internet.TextBody;

public class CursorToMessage {
    
    private static final String REFERENCE_UID_TEMPLATE = "<%s.%s@smssync.studer.tv>";
    
    private static final String[] PHONE_PROJECTION = new String[] {
            Phones.PERSON_ID, People.NAME, Phones.NUMBER
    };

    private static final String[] EMAIL_PROJECTION = new String[] {
        ContactMethods.DATA
    };

    private static final String UNKNOWN_NUMBER = "unknown_number";
    
    private static final String UNKNOWN_EMAIL = "unknown.email";
    
    private static final String UNKNOWN_PERSON = "unknown.person";

    private static final int MAX_PEOPLE_CACHE_SIZE = 100;

    private Context mContext;

    private Address mUserAddress;

    private Map<String, PersonRecord> mPeopleCache;
    
    private String mReferenceValue;
    
    private boolean mMarkAsRead = false;

    public CursorToMessage(Context ctx, String userEmail) {
        mContext = ctx;
        mPeopleCache = new HashMap<String, PersonRecord>();
        mUserAddress = new Address(userEmail);
        
        mReferenceValue = PrefStore.getReferenceUid(ctx);
        if (mReferenceValue == null) {
            mReferenceValue = generateReferenceValue();
            PrefStore.setReferenceUid(ctx, mReferenceValue);
        }
        
        mMarkAsRead = PrefStore.getMarkAsRead(ctx);
    }

    public ConversionResult cursorToMessageArray(Cursor cursor, int maxEntries)
            throws MessagingException {
        List<Message> messageList = new ArrayList<Message>(maxEntries);
        long maxDate = PrefStore.DEFAULT_MAX_SYNCED_DATE;

        String[] columns = cursor.getColumnNames();
        int indexDate = cursor.getColumnIndex(SmsConsts.DATE);
        while (cursor.moveToNext()) {
            HashMap<String, String> msgMap = new HashMap<String, String>(columns.length);

            long date = cursor.getLong(indexDate);
            if (date > maxDate) {
                maxDate = date;
            }
            for (int i = 0; i < columns.length; i++) {
                msgMap.put(columns[i], cursor.getString(i));
            }
            messageList.add(messageFromHashMap(msgMap));
            if (messageList.size() == maxEntries) {
                // Only consume up to 'maxEntries' items.
                break;
            }
        }
        //TODO: Be more clever and MFU or LRU people.
        if (mPeopleCache.size() > MAX_PEOPLE_CACHE_SIZE) {
            mPeopleCache.clear();
        }

        ConversionResult result = new ConversionResult();
        result.maxDate = maxDate;
        result.messageList = messageList;
        return result;
    }

    private Message messageFromHashMap(HashMap<String, String> msgMap) throws MessagingException {
        Message msg = new MimeMessage();

        PersonRecord record = null;
        String address = msgMap.get("address");
        if (address != null) {
            address = address.trim();
            if (address.length() > 0) {
                record = lookupPerson(address);
            }
        }
        
        if (record == null) {
            record = new PersonRecord();
            record._id = address;
            record.name = address;
            record.address = new Address(address + "@" + UNKNOWN_PERSON);
        }

        msg.setSubject("SMS with " + record.name);

        TextBody body = new TextBody(msgMap.get(SmsConsts.BODY));

        int messageType = Integer.valueOf(msgMap.get(SmsConsts.TYPE));
        if (SmsConsts.MESSAGE_TYPE_INBOX == messageType) {
            // Received message
            msg.setFrom(record.address);
            msg.setRecipient(RecipientType.TO, mUserAddress);
        } else {
            // Sent message
            msg.setRecipient(RecipientType.TO, record.address);
            msg.setFrom(mUserAddress);
        }

        msg.setBody(body);
        Date then = new Date(Long.valueOf(msgMap.get(SmsConsts.DATE)));
        msg.setSentDate(then);
        msg.setInternalDate(then);
        // Threading by person ID, not by thread ID. I think this value is more
        // stable.
        msg.setHeader("References", String.format(REFERENCE_UID_TEMPLATE, mReferenceValue,
                record._id));
        
        msg.setHeader("X-smssync-id", msgMap.get(SmsConsts.ID));
        msg.setHeader("X-smssync-address", address);
        msg.setHeader("X-smssync-type", msgMap.get(SmsConsts.TYPE));
        msg.setHeader("X-smssync-date", msgMap.get(SmsConsts.DATE));
        msg.setHeader("X-smssync-thread", msgMap.get(SmsConsts.THREAD_ID));
        msg.setHeader("X-smssync-read", msgMap.get(SmsConsts.READ));
        msg.setHeader("X-smssync-status", msgMap.get(SmsConsts.STATUS));
        msg.setHeader("X-smssync-protocol", msgMap.get(SmsConsts.PROTOCOL));
        msg.setHeader("X-smssync-service_center", msgMap.get(SmsConsts.SERVICE_CENTER));
        msg.setHeader("X-smssync-backup_time", new Date().toGMTString());
        msg.setFlag(Flag.SEEN, mMarkAsRead);
        
        return msg;
    }

    private PersonRecord lookupPerson(String address) {
        if (!mPeopleCache.containsKey(address)) {
            // Look phone number
            Uri personUri = Uri.withAppendedPath(Phones.CONTENT_FILTER_URL, address);
            Cursor phoneCursor = mContext.getContentResolver().query(personUri, PHONE_PROJECTION,
                    null, null, null);
            if (phoneCursor.moveToFirst()) {
                int indexPersonId = phoneCursor.getColumnIndex(Phones.PERSON_ID);
                int indexName = phoneCursor.getColumnIndex(People.NAME);
                int indexNumber = phoneCursor.getColumnIndex(Phones.NUMBER);
                long personId = phoneCursor.getLong(indexPersonId);
                String name = phoneCursor.getString(indexName);
                String number = phoneCursor.getString(indexNumber);
                phoneCursor.close();

                String primaryEmail = getEmail(number, personId);

                PersonRecord record = new PersonRecord();
                record._id = String.valueOf(personId);
                record.name = name;
                record.address = new Address(primaryEmail, name);

                mPeopleCache.put(address, record);
            } else {
                Log.v(Consts.TAG, "Looked up unknown address: " + address);
                return null;
            }
        }
        return mPeopleCache.get(address);
    }

    private String getEmail(String number, long personId) {
        String primaryEmail = null;
        String selection = ContactMethods.PERSON_ID + " = ?";
        String[] selectionArgs = new String[] { String.valueOf(personId) };
        if (personId > 0) {
            // Get all e-mail addresses for that person.
            Cursor emailCursor = mContext.getContentResolver().query(
                    ContactMethods.CONTENT_EMAIL_URI, EMAIL_PROJECTION,
                    selection, selectionArgs, null);
            int indexData = emailCursor.getColumnIndex(ContactMethods.DATA);
            
            // Loop over cursor and find a Gmail address for that person.
            // If there is none, pick first e-mail address.
            String firstEmail = null;
            String gmailEmail = null;
            while (emailCursor.moveToNext()) {
                String tmpEmail = emailCursor.getString(indexData);
                if (firstEmail == null) {
                    firstEmail = tmpEmail;
                }
                if (isGmailAddress(tmpEmail)) {
                    gmailEmail = tmpEmail;
                    break;
                }
            }
            emailCursor.close();
            primaryEmail = (gmailEmail != null) ? gmailEmail : firstEmail;
        }
        // Return found e-mail address or a dummy "unknown e-mail address"
        // if there is none.
        if (primaryEmail == null) {
            primaryEmail = getUnknownEmail(number);
        }
        return primaryEmail;
    }

    private static String getUnknownEmail(String number) {
        String no = (number == null) ? UNKNOWN_NUMBER : number;
        return no + "@" + UNKNOWN_EMAIL;
    }
    
    /** Returns whether the given e-mail address is a Gmail address or not. */
    private static boolean isGmailAddress(String email) {
        return email.endsWith("gmail.com") || email.endsWith("googlemail.com");
    }
    
    private static String generateReferenceValue() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 24; i++) {
            sb.append(Integer.toString((int)(Math.random() * 35), 36));
        }
        return sb.toString();
    }

    public static class ConversionResult {
        public long maxDate;

        public List<Message> messageList;
    }

    private static class PersonRecord {
        String _id;

        String name;

        Address address;
    }
}




Java Source Code List

tv.studer.smssync.Alarms.java
tv.studer.smssync.Consts.java
tv.studer.smssync.CursorToMessage.java
tv.studer.smssync.PrefStore.java
tv.studer.smssync.SmsBroadcastReceiver.java
tv.studer.smssync.SmsConsts.java
tv.studer.smssync.SmsSyncService.java
tv.studer.smssync.SmsSync.java