diff --git a/src/org/geometerplus/android/fbreader/api/Api.java b/src/org/geometerplus/android/fbreader/api/Api.java index 77fc2e43b..2d5fbd274 100644 --- a/src/org/geometerplus/android/fbreader/api/Api.java +++ b/src/org/geometerplus/android/fbreader/api/Api.java @@ -19,6 +19,8 @@ package org.geometerplus.android.fbreader.api; +import java.util.List; + public interface Api { void connect(); void disconnect(); @@ -29,8 +31,8 @@ public interface Api { // book information String getBookLanguage() throws ApiException; String getBookTitle() throws ApiException; - //String getBookAuthors() throws ApiException; - //String getBookTags() throws ApiException; + //List getBookAuthors() throws ApiException; + List getBookTags() throws ApiException; String getBookFileName() throws ApiException; // text information @@ -46,4 +48,6 @@ public interface Api { // manage view void setPageStart(TextPosition position) throws ApiException; + void highlightArea(TextPosition start, TextPosition end) throws ApiException; + void clearHighlighting() throws ApiException; } diff --git a/src/org/geometerplus/android/fbreader/api/ApiServiceConnection.java b/src/org/geometerplus/android/fbreader/api/ApiClientImplementation.java similarity index 74% rename from src/org/geometerplus/android/fbreader/api/ApiServiceConnection.java rename to src/org/geometerplus/android/fbreader/api/ApiClientImplementation.java index 301e5163d..87d94b341 100644 --- a/src/org/geometerplus/android/fbreader/api/ApiServiceConnection.java +++ b/src/org/geometerplus/android/fbreader/api/ApiClientImplementation.java @@ -19,16 +19,18 @@ package org.geometerplus.android.fbreader.api; +import java.util.*; + import android.content.*; import android.os.IBinder; -public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods { +public class ApiClientImplementation implements ServiceConnection, Api, ApiMethods { private static String ACTION_API = "android.fbreader.action.API"; private final Context myContext; private volatile ApiInterface myInterface; - public ApiServiceConnection(Context context) { + public ApiClientImplementation(Context context) { myContext = context; connect(); } @@ -59,20 +61,38 @@ public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods myInterface = null; } - private synchronized ApiObject request(int method, ApiObject[] params) throws ApiException { + private synchronized void checkConnection() throws ApiException { if (myInterface == null) { throw new ApiException("Not connected to FBReader"); } - final ApiObject object; + } + + private synchronized ApiObject request(int method, ApiObject[] params) throws ApiException { + checkConnection(); try { - object = myInterface.request(method, params); + final ApiObject object = myInterface.request(method, params); + if (object instanceof ApiObject.Error) { + throw new ApiException(((ApiObject.Error)object).Message); + } + return object; } catch (android.os.RemoteException e) { throw new ApiException(e); } - if (object instanceof ApiObject.Error) { - throw new ApiException(((ApiObject.Error)object).Message); + } + + private synchronized List requestList(int method, ApiObject[] params) throws ApiException { + checkConnection(); + try { + final List list = myInterface.requestList(method, params); + for (ApiObject object : list) { + if (object instanceof ApiObject.Error) { + throw new ApiException(((ApiObject.Error)object).Message); + } + } + return list; + } catch (android.os.RemoteException e) { + throw new ApiException(e); } - return object; } private String requestString(int method, ApiObject[] params) throws ApiException { @@ -107,6 +127,18 @@ public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods return (TextPosition)object; } + private List requestStringList(int method, ApiObject[] params) throws ApiException { + final List list = requestList(method, params); + final ArrayList stringList = new ArrayList(list.size()); + for (ApiObject object : list) { + if (!(object instanceof ApiObject.String)) { + throw new ApiException("Cannot cast an element returned from method " + method + " to String"); + } + stringList.add(((ApiObject.String)object).Value); + } + return stringList; + } + private static final ApiObject[] EMPTY_PARAMETERS = new ApiObject[0]; private static ApiObject[] envelope(int value) { @@ -125,6 +157,10 @@ public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods return requestString(GET_BOOK_TITLE, EMPTY_PARAMETERS); } + public List getBookTags() throws ApiException { + return requestStringList(GET_BOOK_TAGS, EMPTY_PARAMETERS); + } + public String getBookFileName() throws ApiException { return requestString(GET_BOOK_FILENAME, EMPTY_PARAMETERS); } @@ -145,10 +181,6 @@ public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods return requestBoolean(IS_PAGE_END_OF_TEXT, EMPTY_PARAMETERS); } - public void setPageStart(TextPosition position) throws ApiException { - request(SET_PAGE_START, new ApiObject[] { position }); - } - public int getParagraphsNumber() throws ApiException { return requestInt(GET_PARAGRAPHS_NUMBER, EMPTY_PARAMETERS); } @@ -160,4 +192,16 @@ public class ApiServiceConnection implements ServiceConnection, Api, ApiMethods public int getElementsNumber(int paragraphIndex) throws ApiException { return requestInt(GET_ELEMENTS_NUMBER, envelope(paragraphIndex)); } + + public void setPageStart(TextPosition position) throws ApiException { + request(SET_PAGE_START, new ApiObject[] { position }); + } + + public void highlightArea(TextPosition start, TextPosition end) throws ApiException { + request(HIGHLIGHT_AREA, new ApiObject[] { start, end }); + } + + public void clearHighlighting() throws ApiException { + request(CLEAR_HIGHLIGHTING, EMPTY_PARAMETERS); + } } diff --git a/src/org/geometerplus/android/fbreader/api/ApiInterface.aidl b/src/org/geometerplus/android/fbreader/api/ApiInterface.aidl index 3766b90b9..9085bb635 100644 --- a/src/org/geometerplus/android/fbreader/api/ApiInterface.aidl +++ b/src/org/geometerplus/android/fbreader/api/ApiInterface.aidl @@ -23,4 +23,6 @@ import org.geometerplus.android.fbreader.api.ApiObject; interface ApiInterface { ApiObject request(int method, in ApiObject[] parameters); + List requestList(int method, in ApiObject[] parameters); + Map requestMap(int method, in ApiObject[] parameters); } diff --git a/src/org/geometerplus/android/fbreader/api/ApiMethods.java b/src/org/geometerplus/android/fbreader/api/ApiMethods.java index a41b8c303..29d3e12bf 100644 --- a/src/org/geometerplus/android/fbreader/api/ApiMethods.java +++ b/src/org/geometerplus/android/fbreader/api/ApiMethods.java @@ -49,6 +49,8 @@ interface ApiMethods { int IS_PAGE_END_OF_TEXT = 703; int IS_PAGE_END_OF_SECTION = 704; - // view change + // view management int SET_PAGE_START = 801; + int HIGHLIGHT_AREA = 802; + int CLEAR_HIGHLIGHTING = 803; } diff --git a/src/org/geometerplus/android/fbreader/api/ApiImplementation.java b/src/org/geometerplus/android/fbreader/api/ApiServerImplementation.java similarity index 78% rename from src/org/geometerplus/android/fbreader/api/ApiImplementation.java rename to src/org/geometerplus/android/fbreader/api/ApiServerImplementation.java index 827a35953..ec4c82768 100644 --- a/src/org/geometerplus/android/fbreader/api/ApiImplementation.java +++ b/src/org/geometerplus/android/fbreader/api/ApiServerImplementation.java @@ -19,31 +19,31 @@ package org.geometerplus.android.fbreader.api; +import java.util.*; + import org.geometerplus.zlibrary.core.library.ZLibrary; import org.geometerplus.zlibrary.text.view.*; import org.geometerplus.fbreader.fbreader.FBReaderApp; -public class ApiImplementation extends ApiInterface.Stub implements ApiMethods { +public class ApiServerImplementation extends ApiInterface.Stub implements ApiMethods { private final FBReaderApp myReader = (FBReaderApp)FBReaderApp.Instance(); + private ApiObject.Error unsupportedMethodError(int method) { + return new ApiObject.Error("Unsupported method code: " + method); + } + @Override public ApiObject request(int method, ApiObject[] parameters) { try { switch (method) { case GET_FBREADER_VERSION: - return ApiObject.envelope( - ZLibrary.Instance().getVersionName() - ); + return ApiObject.envelope(ZLibrary.Instance().getVersionName()); case GET_BOOK_LANGUAGE: - return ApiObject.envelope( - myReader.Model.Book.getLanguage() - ); + return ApiObject.envelope(myReader.Model.Book.getLanguage()); case GET_BOOK_TITLE: - return ApiObject.envelope( - myReader.Model.Book.getTitle() - ); + return ApiObject.envelope(myReader.Model.Book.getTitle()); case GET_PARAGRAPHS_NUMBER: return ApiObject.envelope(getParagraphsNumber()); case GET_ELEMENTS_NUMBER: @@ -63,18 +63,31 @@ public class ApiImplementation extends ApiInterface.Stub implements ApiMethods { case IS_PAGE_END_OF_TEXT: return ApiObject.envelope(isPageEndOfText()); case SET_PAGE_START: - setPageStart( - (TextPosition)parameters[0] - ); + setPageStart((TextPosition)parameters[0]); + return ApiObject.Void.Instance; + case HIGHLIGHT_AREA: + return ApiObject.Void.Instance; + case CLEAR_HIGHLIGHTING: return ApiObject.Void.Instance; default: - return new ApiObject.Error("Unsupported method code: " + method); + return unsupportedMethodError(method); } } catch (Throwable e) { return new ApiObject.Error("Exception in method " + method + ": " + e); } } + @Override + public List requestList(int method, ApiObject[] parameters) { + return Collections.singletonList(unsupportedMethodError(method)); + } + + @Override + public Map requestMap(int method, ApiObject[] parameters) { + final ApiObject error = unsupportedMethodError(method); + return Collections.singletonMap(error, error); + } + private TextPosition getTextPosition(ZLTextWordCursor cursor) { return new TextPosition( cursor.getParagraphIndex(), diff --git a/src/org/geometerplus/android/fbreader/api/ApiService.java b/src/org/geometerplus/android/fbreader/api/ApiService.java index 8f0e2c230..31a280782 100644 --- a/src/org/geometerplus/android/fbreader/api/ApiService.java +++ b/src/org/geometerplus/android/fbreader/api/ApiService.java @@ -26,6 +26,6 @@ import android.os.IBinder; public class ApiService extends Service { @Override public IBinder onBind(Intent intent) { - return new ApiImplementation(); + return new ApiServerImplementation(); } }