diff options
author | Daniel Gultsch <daniel@gultsch.de> | 2015-09-22 07:54:27 +0200 |
---|---|---|
committer | Daniel Gultsch <daniel@gultsch.de> | 2015-09-22 07:54:27 +0200 |
commit | 6f7fb7dec6535710f05a0c3a5923221518196f9c (patch) | |
tree | 08137d8558febac536c0972f3b9830a092b11a0a /src/main/java/eu | |
parent | 9636627ef0cd4f850b993d712d3cdc53053bb957 (diff) | |
parent | a3a13dd9dc69280f84b60321388ce4b8f674f012 (diff) |
Merge pull request #1426 from fiaxh/export_logs
Preference to backup logs to SD card
Diffstat (limited to 'src/main/java/eu')
3 files changed, 208 insertions, 0 deletions
diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index d420c1cd..be827929 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -21,6 +21,7 @@ import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; @@ -407,6 +408,43 @@ public class DatabaseBackend extends SQLiteOpenHelper { return list; } + public Iterable<Message> getMessagesIterable(final Conversation conversation){ + return new Iterable<Message>() { + @Override + public Iterator<Message> iterator() { + class MessageIterator implements Iterator<Message>{ + SQLiteDatabase db = getReadableDatabase(); + String[] selectionArgs = { conversation.getUuid() }; + Cursor cursor = db.query(Message.TABLENAME, null, Message.CONVERSATION + + "=?", selectionArgs, null, null, Message.TIME_SENT + + " ASC", null); + + public MessageIterator() { + cursor.moveToFirst(); + } + + @Override + public boolean hasNext() { + return !cursor.isAfterLast(); + } + + @Override + public Message next() { + Message message = Message.fromCursor(cursor); + cursor.moveToNext(); + return message; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + return new MessageIterator(); + } + }; + } + public Conversation findConversation(final Account account, final Jid contactJid) { SQLiteDatabase db = this.getReadableDatabase(); String[] selectionArgs = { account.getUuid(), diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java new file mode 100644 index 00000000..41b34699 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java @@ -0,0 +1,141 @@ +package eu.siacs.conversations.services; + +import android.app.NotificationManager; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.support.v4.app.NotificationCompat; + +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.persistance.DatabaseBackend; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.xmpp.jid.Jid; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class ExportLogsService extends Service { + + private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsFileDirectory() + "/logs/%s"; + private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n"; + private static final int NOTIFICATION_ID = 1; + private static AtomicBoolean running = new AtomicBoolean(false); + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (running.compareAndSet(false, true)) { + new Thread( + new Runnable() { + DatabaseBackend databaseBackend = DatabaseBackend.getInstance(getBaseContext()); + List<Account> accounts = databaseBackend.getAccounts(); + + @Override + public void run() { + List<Conversation> conversations = databaseBackend.getConversations(Conversation.STATUS_AVAILABLE); + conversations.addAll(databaseBackend.getConversations(Conversation.STATUS_ARCHIVED)); + + NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext()); + mBuilder.setContentTitle(getString(R.string.notification_export_logs_title)) + .setSmallIcon(R.drawable.ic_notification) + .setProgress(conversations.size(), 0, false); + startForeground(NOTIFICATION_ID, mBuilder.build()); + + int progress = 0; + for (Conversation conversation : conversations) { + writeToFile(conversation); + progress++; + mBuilder.setProgress(conversations.size(), progress, false); + mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build()); + } + + running.set(false); + stopForeground(true); + } + + private void writeToFile(Conversation conversation) { + Jid accountJid = resolveAccountUuid(conversation.getAccountUuid()); + Jid contactJid = conversation.getJid(); + + File dir = new File(String.format(DIRECTORY_STRING_FORMAT, + accountJid.toBareJid().toString())); + dir.mkdirs(); + + BufferedWriter bw = null; + try { + for (Message message : databaseBackend.getMessagesIterable(conversation)) { + if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) { + String date = simpleDateFormat.format(new Date(message.getTimeSent())); + if (bw == null) { + bw = new BufferedWriter(new FileWriter( + new File(dir, contactJid.toBareJid().toString() + ".txt"))); + } + String jid = null; + switch (message.getStatus()) { + case Message.STATUS_RECEIVED: + jid = getMessageCounterpart(message); + break; + case Message.STATUS_SEND: + case Message.STATUS_SEND_RECEIVED: + case Message.STATUS_SEND_DISPLAYED: + jid = accountJid.toBareJid().toString(); + break; + } + if (jid != null) { + String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody(); + bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid, + body.replace("\\\n", "\\ \n").replace("\n", "\\ \n"))); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + } + + private Jid resolveAccountUuid(String accountUuid) { + for (Account account : accounts) { + if (account.getUuid().equals(accountUuid)) { + return account.getJid(); + } + } + return null; + } + + private String getMessageCounterpart(Message message) { + String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART); + if (trueCounterpart != null) { + return trueCounterpart; + } else { + return message.getCounterpart().toString(); + } + } + }).start(); + } + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } +}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java b/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java new file mode 100644 index 00000000..a4e178bd --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/ExportLogsPreference.java @@ -0,0 +1,29 @@ +package eu.siacs.conversations.ui; + +import android.content.Context; +import android.content.Intent; +import android.preference.Preference; +import android.util.AttributeSet; + +import eu.siacs.conversations.services.ExportLogsService; + +public class ExportLogsPreference extends Preference { + + public ExportLogsPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ExportLogsPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ExportLogsPreference(Context context) { + super(context); + } + + protected void onClick() { + final Intent startIntent = new Intent(getContext(), ExportLogsService.class); + getContext().startService(startIntent); + super.onClick(); + } +}
\ No newline at end of file |