mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 10:49:24 +02:00
use sync options in SynchroniserService
This commit is contained in:
parent
324a48d384
commit
92759bc5ec
3 changed files with 95 additions and 27 deletions
|
@ -25,7 +25,7 @@ import java.util.Map;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
public final class ServiceNetworkContext extends AndroidNetworkContext {
|
public class ServiceNetworkContext extends AndroidNetworkContext {
|
||||||
private final Service myService;
|
private final Service myService;
|
||||||
|
|
||||||
public ServiceNetworkContext(Service service) {
|
public ServiceNetworkContext(Service service) {
|
||||||
|
|
|
@ -24,6 +24,8 @@ import java.util.*;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
|
||||||
import org.json.simple.JSONValue;
|
import org.json.simple.JSONValue;
|
||||||
|
@ -32,6 +34,7 @@ import org.geometerplus.zlibrary.core.filesystem.ZLPhysicalFile;
|
||||||
import org.geometerplus.zlibrary.core.network.*;
|
import org.geometerplus.zlibrary.core.network.*;
|
||||||
import org.geometerplus.zlibrary.ui.android.network.SQLiteCookieDatabase;
|
import org.geometerplus.zlibrary.ui.android.network.SQLiteCookieDatabase;
|
||||||
import org.geometerplus.fbreader.book.*;
|
import org.geometerplus.fbreader.book.*;
|
||||||
|
import org.geometerplus.fbreader.fbreader.options.SyncOptions;
|
||||||
import org.geometerplus.android.fbreader.libraryService.BookCollectionShadow;
|
import org.geometerplus.android.fbreader.libraryService.BookCollectionShadow;
|
||||||
import org.geometerplus.android.fbreader.network.auth.ServiceNetworkContext;
|
import org.geometerplus.android.fbreader.network.auth.ServiceNetworkContext;
|
||||||
|
|
||||||
|
@ -41,6 +44,7 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
Uploaded(Book.SYNCHRONIZED_LABEL),
|
Uploaded(Book.SYNCHRONIZED_LABEL),
|
||||||
ToBeDeleted(Book.SYNC_DELETED_LABEL),
|
ToBeDeleted(Book.SYNC_DELETED_LABEL),
|
||||||
Failure(Book.SYNC_FAILURE_LABEL),
|
Failure(Book.SYNC_FAILURE_LABEL),
|
||||||
|
SyncronizationDisabled(null),
|
||||||
FailedPreviuousTime(null),
|
FailedPreviuousTime(null),
|
||||||
HashNotComputed(null);
|
HashNotComputed(null);
|
||||||
|
|
||||||
|
@ -58,14 +62,31 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ZLNetworkContext myNetworkContext = new ServiceNetworkContext(this);
|
private final ConnectivityManager myConnectivityManager =
|
||||||
|
(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
private final SyncOptions mySyncOptions = new SyncOptions();
|
||||||
|
|
||||||
|
private static final class SyncronizationDisabledException extends RuntimeException {
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ZLNetworkContext myNetworkContext = new ServiceNetworkContext(this) {
|
||||||
|
@Override
|
||||||
|
protected void perform(ZLNetworkRequest request, int socketTimeout, int connectionTimeout) throws ZLNetworkException {
|
||||||
|
if (!canPerformRequest()) {
|
||||||
|
throw new SyncronizationDisabledException();
|
||||||
|
}
|
||||||
|
super.perform(request, socketTimeout, connectionTimeout);
|
||||||
|
}
|
||||||
|
};
|
||||||
private final BookCollectionShadow myCollection = new BookCollectionShadow();
|
private final BookCollectionShadow myCollection = new BookCollectionShadow();
|
||||||
private static volatile Thread ourSynchronizationThread;
|
private static volatile Thread ourSynchronizationThread;
|
||||||
|
|
||||||
private final List<Book> myQueue = Collections.synchronizedList(new LinkedList<Book>());
|
private final List<Book> myQueue = Collections.synchronizedList(new LinkedList<Book>());
|
||||||
private final Set<Book> myProcessed = new HashSet<Book>();
|
private final Set<Book> myProcessed = new HashSet<Book>();
|
||||||
|
|
||||||
private final Set<String> myActualHashesFromServer = new HashSet<String>();
|
private final Set<String> myActualHashesFromServer = new HashSet<String>();
|
||||||
private final Set<String> myDeletedHashesFromServer = new HashSet<String>();
|
private final Set<String> myDeletedHashesFromServer = new HashSet<String>();
|
||||||
|
private volatile boolean myHashTablesAreInitialized = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
@ -80,6 +101,54 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void clearHashTables() {
|
||||||
|
myActualHashesFromServer.clear();
|
||||||
|
myDeletedHashesFromServer.clear();
|
||||||
|
myHashTablesAreInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void initHashTables() {
|
||||||
|
if (myHashTablesAreInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
myNetworkContext.perform(new PostRequest("all.hashes", null) {
|
||||||
|
@Override
|
||||||
|
public void processResponse(Object response) {
|
||||||
|
final Map<String,List<String>> map = (Map<String,List<String>>)response;
|
||||||
|
myActualHashesFromServer.addAll(map.get("actual"));
|
||||||
|
myDeletedHashesFromServer.addAll(map.get("deleted"));
|
||||||
|
myHashTablesAreInitialized = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
System.err.println(String.format("RECEIVED: %s/%s HASHES", myActualHashesFromServer.size(), myDeletedHashesFromServer.size()));
|
||||||
|
} catch (SyncronizationDisabledException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canPerformRequest() {
|
||||||
|
if (!mySyncOptions.Enabled.getValue()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mySyncOptions.UploadAllBooks.getValue()) {
|
||||||
|
default:
|
||||||
|
case never:
|
||||||
|
return false;
|
||||||
|
case always:
|
||||||
|
return myConnectivityManager.getActiveNetworkInfo().isConnected();
|
||||||
|
case viaWifi:
|
||||||
|
{
|
||||||
|
final NetworkInfo info = myConnectivityManager.getActiveNetworkInfo();
|
||||||
|
return info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void run() {
|
public synchronized void run() {
|
||||||
myCollection.addListener(this);
|
myCollection.addListener(this);
|
||||||
|
@ -90,23 +159,7 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
int count = 0;
|
int count = 0;
|
||||||
final Map<SyncStatus,Integer> statusCounts = new HashMap<SyncStatus,Integer>();
|
final Map<SyncStatus,Integer> statusCounts = new HashMap<SyncStatus,Integer>();
|
||||||
try {
|
try {
|
||||||
myActualHashesFromServer.clear();
|
clearHashTables();
|
||||||
myDeletedHashesFromServer.clear();
|
|
||||||
try {
|
|
||||||
myNetworkContext.perform(new PostRequest("all.hashes", null) {
|
|
||||||
@Override
|
|
||||||
public void processResponse(Object response) {
|
|
||||||
final Map<String,List<String>> map = (Map<String,List<String>>)response;
|
|
||||||
myActualHashesFromServer.addAll(map.get("actual"));
|
|
||||||
myDeletedHashesFromServer.addAll(map.get("deleted"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
System.err.println(String.format("RECEIVED: %s/%s HASHES", myActualHashesFromServer.size(), myDeletedHashesFromServer.size()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
System.err.println("DO NOT SYNCHRONIZE: ALL HASHES REQUEST FAILED");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (BookQuery q = new BookQuery(new Filter.Empty(), 20);; q = q.next()) {
|
for (BookQuery q = new BookQuery(new Filter.Empty(), 20);; q = q.next()) {
|
||||||
final List<Book> books = myCollection.books(q);
|
final List<Book> books = myCollection.books(q);
|
||||||
if (books.isEmpty()) {
|
if (books.isEmpty()) {
|
||||||
|
@ -210,6 +263,14 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
}
|
}
|
||||||
|
|
||||||
private SyncStatus uploadBookToServer(Book book) {
|
private SyncStatus uploadBookToServer(Book book) {
|
||||||
|
try {
|
||||||
|
return uploadBookToServerInternal(book);
|
||||||
|
} catch (SyncronizationDisabledException e) {
|
||||||
|
return SyncStatus.SyncronizationDisabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SyncStatus uploadBookToServerInternal(Book book) {
|
||||||
final ZLPhysicalFile file = book.File.getPhysicalFile();
|
final ZLPhysicalFile file = book.File.getPhysicalFile();
|
||||||
final String hash = myCollection.getHash(book);
|
final String hash = myCollection.getHash(book);
|
||||||
final boolean force = book.labels().contains(Book.SYNC_TOSYNC_LABEL);
|
final boolean force = book.labels().contains(Book.SYNC_TOSYNC_LABEL);
|
||||||
|
@ -222,6 +283,9 @@ public class SynchroniserService extends Service implements IBookCollection.List
|
||||||
} else if (!force && book.labels().contains(Book.SYNC_FAILURE_LABEL)) {
|
} else if (!force && book.labels().contains(Book.SYNC_FAILURE_LABEL)) {
|
||||||
return SyncStatus.FailedPreviuousTime;
|
return SyncStatus.FailedPreviuousTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initHashTables();
|
||||||
|
|
||||||
final Map<String,Object> result = new HashMap<String,Object>();
|
final Map<String,Object> result = new HashMap<String,Object>();
|
||||||
final PostRequest verificationRequest =
|
final PostRequest verificationRequest =
|
||||||
new PostRequest("book.status.by.hash", Collections.singletonMap("sha1", hash)) {
|
new PostRequest("book.status.by.hash", Collections.singletonMap("sha1", hash)) {
|
||||||
|
|
|
@ -59,7 +59,15 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent
|
||||||
getAccountOption(host, realm).setValue(accountName != null ? accountName : "");
|
getAccountOption(host, realm).setValue(accountName != null ? accountName : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean performQuietly(ZLNetworkRequest request) {
|
protected void perform(ZLNetworkRequest request, int socketTimeout, int connectionTimeout) throws ZLNetworkException {
|
||||||
|
myManager.perform(request, this, socketTimeout, connectionTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void perform(ZLNetworkRequest request) throws ZLNetworkException {
|
||||||
|
perform(request, 30000, 15000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean performQuietly(ZLNetworkRequest request) {
|
||||||
try {
|
try {
|
||||||
perform(request);
|
perform(request);
|
||||||
return true;
|
return true;
|
||||||
|
@ -68,11 +76,7 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void perform(ZLNetworkRequest request) throws ZLNetworkException {
|
public final void perform(List<? extends ZLNetworkRequest> requests) throws ZLNetworkException {
|
||||||
myManager.perform(request, this, 30000, 15000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void perform(List<? extends ZLNetworkRequest> requests) throws ZLNetworkException {
|
|
||||||
if (requests.size() == 0) {
|
if (requests.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +111,7 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void downloadToFile(String url, final File outFile, final int bufferSize) throws ZLNetworkException {
|
private final void downloadToFile(String url, final File outFile, final int bufferSize) throws ZLNetworkException {
|
||||||
myManager.perform(new ZLNetworkRequest.Get(url) {
|
perform(new ZLNetworkRequest.Get(url) {
|
||||||
public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException {
|
public void handleStream(InputStream inputStream, int length) throws IOException, ZLNetworkException {
|
||||||
OutputStream outStream = new FileOutputStream(outFile);
|
OutputStream outStream = new FileOutputStream(outFile);
|
||||||
try {
|
try {
|
||||||
|
@ -123,7 +127,7 @@ public abstract class ZLNetworkContext implements ZLNetworkManager.BearerAuthent
|
||||||
outStream.close();
|
outStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, this, 0, 0);
|
}, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZLStringOption getAccountOption(String host, String realm) {
|
private ZLStringOption getAccountOption(String host, String realm) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue