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 eu.siacs.conversations.R;
11import eu.siacs.conversations.entities.Account;
12import eu.siacs.conversations.entities.Conversation;
13import eu.siacs.conversations.entities.Message;
14import eu.siacs.conversations.persistance.DatabaseBackend;
15import eu.siacs.conversations.persistance.FileBackend;
16import eu.siacs.conversations.xmpp.jid.Jid;
17
18import java.io.BufferedWriter;
19import java.io.File;
20import java.io.FileWriter;
21import java.io.IOException;
22import java.text.SimpleDateFormat;
23import java.util.Date;
24import java.util.List;
25import java.util.concurrent.atomic.AtomicBoolean;
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.getConversationsFileDirectory() + "/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
35 @Override
36 public int onStartCommand(Intent intent, int flags, int startId) {
37 if (running.compareAndSet(false, true)) {
38 new Thread(
39 new Runnable() {
40 DatabaseBackend databaseBackend = DatabaseBackend.getInstance(getBaseContext());
41 List<Account> accounts = databaseBackend.getAccounts();
42
43 @Override
44 public void run() {
45 List<Conversation> conversations = databaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
46 conversations.addAll(databaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
47
48 NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
49 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
50 mBuilder.setContentTitle(getString(R.string.notification_export_logs_title))
51 .setSmallIcon(R.drawable.ic_notification)
52 .setProgress(conversations.size(), 0, false);
53 startForeground(NOTIFICATION_ID, mBuilder.build());
54
55 int progress = 0;
56 for (Conversation conversation : conversations) {
57 writeToFile(conversation);
58 progress++;
59 mBuilder.setProgress(conversations.size(), progress, false);
60 mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
61 }
62
63 running.set(false);
64 stopForeground(true);
65 }
66
67 private void writeToFile(Conversation conversation) {
68 Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
69 Jid contactJid = conversation.getJid();
70
71 File dir = new File(String.format(DIRECTORY_STRING_FORMAT,
72 accountJid.toBareJid().toString()));
73 dir.mkdirs();
74
75 BufferedWriter bw = null;
76 try {
77 for (Message message : databaseBackend.getMessagesIterable(conversation)) {
78 if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) {
79 String date = simpleDateFormat.format(new Date(message.getTimeSent()));
80 if (bw == null) {
81 bw = new BufferedWriter(new FileWriter(
82 new File(dir, contactJid.toBareJid().toString() + ".txt")));
83 }
84 String jid = null;
85 switch (message.getStatus()) {
86 case Message.STATUS_RECEIVED:
87 jid = getMessageCounterpart(message);
88 break;
89 case Message.STATUS_SEND:
90 case Message.STATUS_SEND_RECEIVED:
91 case Message.STATUS_SEND_DISPLAYED:
92 jid = accountJid.toBareJid().toString();
93 break;
94 }
95 if (jid != null) {
96 String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody();
97 bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid,
98 body.replace("\\\n", "\\ \n").replace("\n", "\\ \n")));
99 }
100 }
101 }
102 } catch (IOException e) {
103 e.printStackTrace();
104 } finally {
105 try {
106 if (bw != null) {
107 bw.close();
108 }
109 } catch (IOException e1) {
110 e1.printStackTrace();
111 }
112 }
113 }
114
115 private Jid resolveAccountUuid(String accountUuid) {
116 for (Account account : accounts) {
117 if (account.getUuid().equals(accountUuid)) {
118 return account.getJid();
119 }
120 }
121 return null;
122 }
123
124 private String getMessageCounterpart(Message message) {
125 String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART);
126 if (trueCounterpart != null) {
127 return trueCounterpart;
128 } else {
129 return message.getCounterpart().toString();
130 }
131 }
132 }).start();
133 }
134 return START_STICKY;
135 }
136
137 @Override
138 public IBinder onBind(Intent intent) {
139 return null;
140 }
141}