package com.stanleycen.facebookanalytics; import android.app.Activity; import android.app.ProgressDialog; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import org.joda.time.DateTime; import org.json.JSONArray; import org.json.JSONException; import java.util.HashMap; /** * Created by scen on 8/29/13. */ public class UnifiedMessaging { public final static long LARGE_TIMESTAMP = 10000000000000000L; public final static int API_WAIT = 1500; public final static int API_TIMEOUT_WAIT = 1000 * 60 * 5; private final static String GET_THREADS_FQL = "SELECT former_participants,is_group_conversation,title,num_messages,participants,thread_id,timestamp FROM unified_thread WHERE folder=\"inbox\" AND timestamp < %d LIMIT 500"; private final static String GET_MESSAGES_FQL = "SELECT attachment_map,attachments,body,coordinates,message_id,sender,timestamp,shares,share_map,tags FROM unified_message WHERE thread_id=\"%s\" AND timestamp > %d LIMIT 500"; public static String getThreadFQL(long timestamp) { return String.format(GET_THREADS_FQL, timestamp); } public static String getMessagesFQL(String threadId, long timestamp) { return String.format(GET_MESSAGES_FQL, threadId, timestamp); } public static FBData readAllFromDatabase(Activity activity, final ProgressDialog dialog) { FBData fbData = new FBData(); DatabaseHandler dbHelper = GlobalApp.get().db; SQLiteDatabase db = dbHelper.getReadableDatabase(); String lastupdate = dbHelper.getKeyVal("lastupdate"); String collectionMethod = dbHelper.getKeyVal("collectionmethod"); if (lastupdate != null && collectionMethod != null) { fbData.lastUpdate = new DateTime(Long.parseLong(lastupdate)); fbData.collectionMethod = FBData.CollectionMethod.values()[Integer.parseInt(collectionMethod)]; Cursor usersCursor = db.rawQuery("SELECT * FROM " + DatabaseHandler.TABLE_USERS, null); usersCursor.moveToFirst(); int len = usersCursor.getCount(); int idx = 0; final int _a = len; activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setIndeterminate(false); dialog.setMax(_a); dialog.setMessage("Loading people"); } }); while (!usersCursor.isAfterLast()) { String id = usersCursor.getString(0); String name = usersCursor.getString(1); fbData.userMap.put(id, new FBUser(id, name)); usersCursor.moveToNext(); final int prog = ++idx; if (prog == len || (idx % 100) == 0) activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(prog); } }); } usersCursor.close(); HashMap<String, FBThread> threadIDMap = new HashMap<String, FBThread>(); HashMap<String, FBMessage> threadAndMessageIDMap = new HashMap<String, FBMessage>(); Cursor threadCursor = db.rawQuery("SELECT * FROM " + DatabaseHandler.TABLE_THREADS + " ORDER BY " + DatabaseHandler.COLUMN_TIMESTAMP + " DESC", null); threadCursor.moveToFirst(); idx = 0; len = threadCursor.getCount(); final int zzz = len; activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(0); dialog.setMax(zzz); dialog.setMessage("Loading conversations"); } }); while (!threadCursor.isAfterLast()) { FBThread fbThread = new FBThread(); fbThread.id = threadCursor.getString(0); threadIDMap.put(fbThread.id, fbThread); fbThread.title = threadCursor.getString(1); fbThread.lastUpdate = new DateTime(threadCursor.getLong(2)); fbThread.isGroupConversation = threadCursor.getInt(3) == 1; try { JSONArray jsonParticipants = new JSONArray(threadCursor.getString(4)); if (jsonParticipants != null) { for (int i = 0; i < jsonParticipants.length(); i++) { fbThread.participants.add(fbData.userMap.get(jsonParticipants.getString(i))); } } } catch (JSONException e) { e.printStackTrace(); } fbThread.messageCount = threadCursor.getInt(5); fbData.threads.add(fbThread); threadCursor.moveToNext(); final int prog = ++idx; if (prog == len || (idx % 20) == 0) activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(prog); } }); } threadCursor.close(); Cursor msgCursor = db.rawQuery("SELECT * FROM " + DatabaseHandler.TABLE_MESSAGES + " ORDER BY timestamp", null); msgCursor.moveToFirst(); len = msgCursor.getCount(); idx = 0; final int xxx = len; activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(0); dialog.setMax(xxx); dialog.setMessage("Loading messages"); } }); while (!msgCursor.isAfterLast()) { FBMessage fbMessage = new FBMessage(); fbMessage.id = msgCursor.getString(0); fbMessage.from = fbData.userMap.get(msgCursor.getString(1)); fbMessage.timestamp = new DateTime(msgCursor.getLong(2)); fbMessage.body = msgCursor.getString(3); fbMessage.thread = msgCursor.getString(4); fbMessage.hasCoordinates = msgCursor.getInt(5) == 1; if (fbMessage.hasCoordinates) { fbMessage.latitude = msgCursor.getFloat(6); fbMessage.longitude = msgCursor.getFloat(7); } fbMessage.source = FBMessage.Source.values()[msgCursor.getInt(9)]; threadAndMessageIDMap.put(fbMessage.thread + fbMessage.id, fbMessage); FBThread parentThread = threadIDMap.get(fbMessage.thread); parentThread.messages.add(fbMessage); msgCursor.moveToNext(); final int prog = ++idx; if (prog == len || (idx % 1000) == 0) activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(prog); } }); } msgCursor.close(); Cursor aCursor = db.rawQuery("SELECT * FROM " + DatabaseHandler.TABLE_ATTACHMENTS, null); aCursor.moveToFirst(); idx = 0; len = aCursor.getCount(); final int yyy = len; activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(0); dialog.setMax(yyy); dialog.setMessage("Loading attachments"); } }); while (!aCursor.isAfterLast()) { FBAttachment fbAttachment = new FBAttachment(); fbAttachment.id = aCursor.getString(0); fbAttachment.type = FBAttachment.Type.values()[aCursor.getInt(6)]; fbAttachment.url = aCursor.getString(3); fbAttachment.thread = aCursor.getString(8); fbAttachment.message = aCursor.getString(7); if (fbAttachment.type == FBAttachment.Type.IMAGE) { fbAttachment.width = aCursor.getInt(1); fbAttachment.height = aCursor.getInt(2); fbAttachment.previewUrl = aCursor.getString(4); fbAttachment.mimeType = aCursor.getString(5); } String combinedId = fbAttachment.thread + fbAttachment.message; threadAndMessageIDMap.get(combinedId).attachments.add(fbAttachment); aCursor.moveToNext(); final int prog = ++idx; if (prog == len || (idx % 10) == 0) activity.runOnUiThread(new Runnable() { @Override public void run() { dialog.setProgress(prog); } }); } aCursor.close(); } db.close(); fbData.computeHighLevelThreadStats(); return fbData; } public static void commitData(FBData fbData) { DatabaseHandler dbHelper = GlobalApp.get().db; SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { dbHelper.clearAllTables(db); dbHelper.insertKeyVal(db, "lastupdate", String.valueOf(fbData.lastUpdate.getMillis())); dbHelper.insertKeyVal(db, "collectionmethod", String.valueOf(fbData.collectionMethod.ordinal())); for (HashMap.Entry<String, FBUser> kv : fbData.userMap.entrySet()) { FBUser user = kv.getValue(); ContentValues cv = new ContentValues(); cv.put(DatabaseHandler.COLUMN_ID, user.id); cv.put(DatabaseHandler.COLUMN_NAME, user.name); db.insert(DatabaseHandler.TABLE_USERS, null, cv); } for (FBThread fbThread : fbData.threads) { commitThread(db, fbThread); } db.setTransactionSuccessful(); GlobalApp.get().fb.fbData = fbData; } catch (Exception e) { } finally { db.endTransaction(); } db.close(); } public static void commitThread(SQLiteDatabase db, FBThread fbThread) { db.delete(DatabaseHandler.TABLE_THREADS, DatabaseHandler.COLUMN_ID + "=?", new String[]{fbThread.id}); db.delete(DatabaseHandler.TABLE_MESSAGES, DatabaseHandler.COLUMN_THREAD + "=?", new String[]{fbThread.id}); db.delete(DatabaseHandler.TABLE_ATTACHMENTS, DatabaseHandler.COLUMN_THREAD + "=?", new String[]{fbThread.id}); ContentValues cv = new ContentValues(); cv.put(DatabaseHandler.COLUMN_ID, fbThread.id); cv.put(DatabaseHandler.COLUMN_TITLE, fbThread.title); cv.put(DatabaseHandler.COLUMN_TIMESTAMP, fbThread.lastUpdate.getMillis()); cv.put(DatabaseHandler.COLUMN_ISGROUP, fbThread.isGroupConversation); JSONArray participantsArray = new JSONArray(); for (FBUser user : fbThread.participants) { participantsArray.put(user.id); } cv.put(DatabaseHandler.COLUMN_PARTICIPANTS, participantsArray.toString()); cv.put(DatabaseHandler.COLUMN_MESSAGECOUNT, fbThread.messageCount); db.insert(DatabaseHandler.TABLE_THREADS, null, cv); for (FBMessage fbMessage : fbThread.messages) { commitMessage(db, fbMessage); } } public static void commitMessage(SQLiteDatabase db, FBMessage fbMessage) { ContentValues cv = new ContentValues(); cv.put(DatabaseHandler.COLUMN_ID, fbMessage.id); cv.put(DatabaseHandler.COLUMN_FROM, fbMessage.from.id); cv.put(DatabaseHandler.COLUMN_TIMESTAMP, fbMessage.timestamp.getMillis()); cv.put(DatabaseHandler.COLUMN_BODY, fbMessage.body); cv.put(DatabaseHandler.COLUMN_THREAD, fbMessage.thread); cv.put(DatabaseHandler.COLUMN_HASCOORD, fbMessage.hasCoordinates); if (fbMessage.hasCoordinates) { cv.put(DatabaseHandler.COLUMN_LATITUDE, fbMessage.latitude); cv.put(DatabaseHandler.COLUMN_LONGITUDE, fbMessage.longitude); } if (!fbMessage.attachments.isEmpty()) { JSONArray attachmentArray = new JSONArray(); for (FBAttachment fbAttachment : fbMessage.attachments) { attachmentArray.put(fbAttachment.id); commitAttachment(db, fbAttachment); } cv.put(DatabaseHandler.COLUMN_ATTACHMENTS, attachmentArray.toString()); } cv.put(DatabaseHandler.COLUMN_SOURCE, fbMessage.source.ordinal()); db.insert(DatabaseHandler.TABLE_MESSAGES, null, cv); } public static void commitAttachment(SQLiteDatabase db, FBAttachment fbAttachment) { ContentValues cv = new ContentValues(); cv.put(DatabaseHandler.COLUMN_ID, fbAttachment.id); cv.put(DatabaseHandler.COLUMN_TYPE, fbAttachment.type.ordinal()); cv.put(DatabaseHandler.COLUMN_URL, fbAttachment.url); cv.put(DatabaseHandler.COLUMN_THREAD, fbAttachment.thread); cv.put(DatabaseHandler.COLUMN_MESSAGE, fbAttachment.message); if (fbAttachment.type == FBAttachment.Type.IMAGE) { cv.put(DatabaseHandler.COLUMN_PREVIEWURL, fbAttachment.previewUrl); cv.put(DatabaseHandler.COLUMN_MIMETYPE, fbAttachment.mimeType); cv.put(DatabaseHandler.COLUMN_HEIGHT, fbAttachment.height); cv.put(DatabaseHandler.COLUMN_WIDTH, fbAttachment.width); } db.insert(DatabaseHandler.TABLE_ATTACHMENTS, null, cv); } }