ExportLogsService.java

  1package eu.siacs.conversations.services;
  2
  3import android.app.NotificationManager;
  4import android.app.Service;
  5import android.content.Context;
  6import android.content.Intent;
  7import android.os.IBinder;
  8import android.support.v4.app.NotificationCompat;
  9
 10import java.io.BufferedWriter;
 11import java.io.File;
 12import java.io.FileWriter;
 13import java.io.IOException;
 14import java.text.SimpleDateFormat;
 15import java.util.Date;
 16import java.util.List;
 17import java.util.concurrent.atomic.AtomicBoolean;
 18
 19import eu.siacs.conversations.R;
 20import eu.siacs.conversations.entities.Account;
 21import eu.siacs.conversations.entities.Conversation;
 22import eu.siacs.conversations.entities.Message;
 23import eu.siacs.conversations.persistance.DatabaseBackend;
 24import eu.siacs.conversations.persistance.FileBackend;
 25import rocks.xmpp.addr.Jid;
 26
 27public class ExportLogsService extends Service {
 28
 29    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
 30    private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsLogsDirectory() + "/logs/%s";
 31    private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n";
 32    private static final int NOTIFICATION_ID = 1;
 33    private static AtomicBoolean running = new AtomicBoolean(false);
 34    private DatabaseBackend mDatabaseBackend;
 35    private List<Account> mAccounts;
 36
 37    @Override
 38    public void onCreate() {
 39        mDatabaseBackend = DatabaseBackend.getInstance(getBaseContext());
 40        mAccounts = mDatabaseBackend.getAccounts();
 41    }
 42
 43    @Override
 44    public int onStartCommand(Intent intent, int flags, int startId) {
 45        if (running.compareAndSet(false, true)) {
 46            new Thread(() -> {
 47                export();
 48                stopForeground(true);
 49                running.set(false);
 50                stopSelf();
 51            }).start();
 52        }
 53        return START_NOT_STICKY;
 54    }
 55
 56    private void export() {
 57        List<Conversation> conversations = mDatabaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
 58        conversations.addAll(mDatabaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
 59        NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 60        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "export");
 61        mBuilder.setContentTitle(getString(R.string.notification_export_logs_title))
 62                .setSmallIcon(R.drawable.ic_import_export_white_24dp)
 63                .setProgress(conversations.size(), 0, false);
 64        startForeground(NOTIFICATION_ID, mBuilder.build());
 65
 66        int progress = 0;
 67        for (Conversation conversation : conversations) {
 68            writeToFile(conversation);
 69            progress++;
 70            mBuilder.setProgress(conversations.size(), progress, false);
 71            if (mNotifyManager != null) {
 72                mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
 73            }
 74        }
 75    }
 76
 77    private void writeToFile(Conversation conversation) {
 78        Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
 79        Jid contactJid = conversation.getJid();
 80
 81        File dir = new File(String.format(DIRECTORY_STRING_FORMAT, accountJid.asBareJid().toString()));
 82        dir.mkdirs();
 83
 84        BufferedWriter bw = null;
 85        try {
 86            for (Message message : mDatabaseBackend.getMessagesIterable(conversation)) {
 87                if (message == null)
 88                    continue;
 89                if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) {
 90                    String date = simpleDateFormat.format(new Date(message.getTimeSent()));
 91                    if (bw == null) {
 92                        bw = new BufferedWriter(new FileWriter(
 93                                new File(dir, contactJid.asBareJid().toString() + ".txt")));
 94                    }
 95                    String jid = null;
 96                    switch (message.getStatus()) {
 97                        case Message.STATUS_RECEIVED:
 98                            jid = getMessageCounterpart(message);
 99                            break;
100                        case Message.STATUS_SEND:
101                        case Message.STATUS_SEND_RECEIVED:
102                        case Message.STATUS_SEND_DISPLAYED:
103                            jid = accountJid.asBareJid().toString();
104                            break;
105                    }
106                    if (jid != null) {
107                        String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody();
108                        bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid,
109                                body.replace("\\\n", "\\ \n").replace("\n", "\\ \n")));
110                    }
111                }
112            }
113        } catch (IOException e) {
114            e.printStackTrace();
115        } finally {
116            try {
117                if (bw != null) {
118                    bw.close();
119                }
120            } catch (IOException e1) {
121                e1.printStackTrace();
122            }
123        }
124    }
125
126    private Jid resolveAccountUuid(String accountUuid) {
127        for (Account account : mAccounts) {
128            if (account.getUuid().equals(accountUuid)) {
129                return account.getJid();
130            }
131        }
132        return null;
133    }
134
135    private String getMessageCounterpart(Message message) {
136        String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART);
137        if (trueCounterpart != null) {
138            return trueCounterpart;
139        } else {
140            return message.getCounterpart().toString();
141        }
142    }
143
144    @Override
145    public IBinder onBind(Intent intent) {
146        return null;
147    }
148}