refactored deleted file detection to monitor entire sd card. fixes #1968
This commit is contained in:
parent
3d372cb339
commit
89a05265ea
|
@ -18,7 +18,7 @@ import android.net.Uri;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.FileObserver;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.PowerManager.WakeLock;
|
import android.os.PowerManager.WakeLock;
|
||||||
|
@ -70,6 +70,7 @@ import eu.siacs.conversations.entities.Blockable;
|
||||||
import eu.siacs.conversations.entities.Bookmark;
|
import eu.siacs.conversations.entities.Bookmark;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.entities.DownloadableFile;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.MucOptions;
|
import eu.siacs.conversations.entities.MucOptions;
|
||||||
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
|
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
|
||||||
|
@ -91,6 +92,7 @@ import eu.siacs.conversations.parser.PresenceParser;
|
||||||
import eu.siacs.conversations.persistance.DatabaseBackend;
|
import eu.siacs.conversations.persistance.DatabaseBackend;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.ui.UiCallback;
|
import eu.siacs.conversations.ui.UiCallback;
|
||||||
|
import eu.siacs.conversations.utils.ConversationsFileObserver;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
import eu.siacs.conversations.utils.ExceptionHelper;
|
import eu.siacs.conversations.utils.ExceptionHelper;
|
||||||
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
|
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
|
||||||
|
@ -211,14 +213,14 @@ public class XmppConnectionService extends Service {
|
||||||
private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
|
private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
|
||||||
private PushManagementService mPushManagementService = new PushManagementService(this);
|
private PushManagementService mPushManagementService = new PushManagementService(this);
|
||||||
private OnConversationUpdate mOnConversationUpdate = null;
|
private OnConversationUpdate mOnConversationUpdate = null;
|
||||||
private final FileObserver fileObserver = new FileObserver(
|
|
||||||
FileBackend.getConversationsImageDirectory()) {
|
|
||||||
|
|
||||||
|
|
||||||
|
private final ConversationsFileObserver fileObserver = new ConversationsFileObserver(
|
||||||
|
Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||||
|
) {
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(int event, String path) {
|
public void onEvent(int event, String path) {
|
||||||
if (event == FileObserver.DELETE) {
|
markFileDeleted(path);
|
||||||
markFileDeleted(path.split("\\.")[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
|
private final OnJinglePacketReceived jingleListener = new OnJinglePacketReceived() {
|
||||||
|
@ -768,7 +770,6 @@ public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
|
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
|
||||||
this.fileObserver.startWatching();
|
this.fileObserver.startWatching();
|
||||||
|
|
||||||
if (Config.supportOpenPgp()) {
|
if (Config.supportOpenPgp()) {
|
||||||
this.pgpServiceConnection = new OpenPgpServiceConnection(getApplicationContext(), "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() {
|
this.pgpServiceConnection = new OpenPgpServiceConnection(getApplicationContext(), "org.sufficientlysecure.keychain", new OpenPgpServiceConnection.OnBound() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -814,6 +815,7 @@ public class XmppConnectionService extends Service {
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
//ignored
|
//ignored
|
||||||
}
|
}
|
||||||
|
fileObserver.stopWatching();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,21 +1286,23 @@ public class XmppConnectionService extends Service {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markFileDeleted(String uuid) {
|
private void markFileDeleted(final String path) {
|
||||||
for (Conversation conversation : getConversations()) {
|
for (Conversation conversation : getConversations()) {
|
||||||
Message message = conversation.findMessageWithFileAndUuid(uuid);
|
conversation.findMessagesWithFiles(new Conversation.OnMessageFound() {
|
||||||
if (message != null) {
|
@Override
|
||||||
if (!getFileBackend().isFileAvailable(message)) {
|
public void onMessageFound(Message message) {
|
||||||
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
|
DownloadableFile file = fileBackend.getFile(message);
|
||||||
final int s = message.getStatus();
|
if (file.getAbsolutePath().equals(path) && !file.exists()) {
|
||||||
if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
|
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
|
||||||
markMessage(message, Message.STATUS_SEND_FAILED);
|
final int s = message.getStatus();
|
||||||
} else {
|
if (s == Message.STATUS_WAITING || s == Message.STATUS_OFFERED || s == Message.STATUS_UNSEND) {
|
||||||
updateConversationUi();
|
markMessage(message, Message.STATUS_SEND_FAILED);
|
||||||
|
} else {
|
||||||
|
updateConversationUi();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package eu.siacs.conversations.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.FileObserver;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2012 Bartek Przybylski
|
||||||
|
* Copyright (C) 2015 ownCloud Inc.
|
||||||
|
* Copyright (C) 2016 Daniel Gultsch
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class ConversationsFileObserver {
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
private final List<SingleFileObserver> mObservers = new ArrayList<>();
|
||||||
|
|
||||||
|
public ConversationsFileObserver(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void startWatching() {
|
||||||
|
Stack<String> stack = new Stack<>();
|
||||||
|
stack.push(path);
|
||||||
|
|
||||||
|
while (!stack.empty()) {
|
||||||
|
String parent = stack.pop();
|
||||||
|
mObservers.add(new SingleFileObserver(parent, FileObserver.DELETE));
|
||||||
|
final File path = new File(parent);
|
||||||
|
final File[] files = path.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(File file : files) {
|
||||||
|
if (file.isDirectory() && !file.getName().equals(".") && !file.getName().equals("..")) {
|
||||||
|
stack.push(file.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(FileObserver observer : mObservers) {
|
||||||
|
observer.startWatching();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stopWatching() {
|
||||||
|
for(FileObserver observer : mObservers) {
|
||||||
|
observer.stopWatching();
|
||||||
|
}
|
||||||
|
mObservers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public void onEvent(int event, String path);
|
||||||
|
|
||||||
|
private class SingleFileObserver extends FileObserver {
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
public SingleFileObserver(String path, int mask) {
|
||||||
|
super(path, mask);
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEvent(int event, String filename) {
|
||||||
|
ConversationsFileObserver.this.onEvent(event, path+'/'+filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue