pull/302/head
gedoor 5 years ago
parent 645319e5a1
commit f23e1b85ba
  1. 358
      app/src/main/java/io/legado/app/api/ReaderProvider.java
  2. 311
      app/src/main/java/io/legado/app/api/ReaderProvider.kt
  3. 18
      app/src/main/java/io/legado/app/web/HttpServer.kt
  4. 2
      app/src/main/java/io/legado/app/web/controller/BookshelfController.kt
  5. 2
      app/src/main/java/io/legado/app/web/controller/SourceController.kt

@ -1,358 +0,0 @@
/*
* Copyright (C) 2020 w568w
*/
package io.legado.app.api;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.CharArrayBuffer;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import com.google.gson.Gson;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import io.legado.app.web.controller.BookshelfController;
import io.legado.app.web.controller.SourceController;
import io.legado.app.web.utils.ReturnData;
/**
* Export book data to other app.
*/
public class ReaderProvider extends ContentProvider {
private enum RequestCode {
saveSource, saveSources, saveBook, deleteSources, getSource, getSources, getBookshelf, getChapterList, getBookContent
}
public static final String POST_BODY_KEY = "json";
public static final String AUTHORITY = "io.legado.app.api.ReaderProvider";
private static UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private SourceController mSourceController;
private BookshelfController mBookshelfController;
static {
sMatcher.addURI(AUTHORITY, "source/insert", RequestCode.saveSource.ordinal());
sMatcher.addURI(AUTHORITY, "sources/insert", RequestCode.saveSources.ordinal());
sMatcher.addURI(AUTHORITY, "book/insert", RequestCode.saveBook.ordinal());
sMatcher.addURI(AUTHORITY, "sources/delete", RequestCode.deleteSources.ordinal());
sMatcher.addURI(AUTHORITY, "source/query", RequestCode.getSource.ordinal());
sMatcher.addURI(AUTHORITY, "sources/query", RequestCode.getSources.ordinal());
sMatcher.addURI(AUTHORITY, "books/query", RequestCode.getBookshelf.ordinal());
sMatcher.addURI(AUTHORITY, "book/chapter/query", RequestCode.getChapterList.ordinal());
sMatcher.addURI(AUTHORITY, "book/content/query", RequestCode.getBookContent.ordinal());
}
public ReaderProvider() {
}
@Override
public int delete(@NotNull Uri uri, String selection, String[] selectionArgs) {
if (sMatcher.match(uri) < 0)
return -1;
switch (RequestCode.values()[sMatcher.match(uri)]) {
case deleteSources:
mSourceController.deleteSources(selection);
break;
default:
throw new IllegalStateException("Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name());
}
return 0;
}
@Override
public String getType(@NotNull Uri uri) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(@NotNull Uri uri, ContentValues values) {
if (sMatcher.match(uri) < 0)
return null;
switch (RequestCode.values()[sMatcher.match(uri)]) {
case saveSource:
mSourceController.saveSource(values.getAsString(POST_BODY_KEY));
break;
case saveBook:
mBookshelfController.saveBook(values.getAsString(POST_BODY_KEY));
case saveSources:
mSourceController.saveSources(values.getAsString(POST_BODY_KEY));
default:
throw new IllegalStateException("Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name());
}
return null;
}
@Override
public boolean onCreate() {
mSourceController = new SourceController();
mBookshelfController = new BookshelfController();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Map<String, ArrayList<String>> map = new HashMap<>();
ArrayList<String> list = new ArrayList<>();
list.add(uri.getQueryParameter("url"));
map.put("url", list);
list = new ArrayList<>();
list.add(uri.getQueryParameter("index"));
map.put("index", list);
if (sMatcher.match(uri) < 0)
return null;
switch (RequestCode.values()[sMatcher.match(uri)]) {
case getSource:
return new SimpleCursor(mSourceController.getSource(map));
case getSources:
return new SimpleCursor(mSourceController.getSources());
case getBookshelf:
return new SimpleCursor(mBookshelfController.getBookshelf());
case getBookContent:
return new SimpleCursor(mBookshelfController.getBookContent(map));
case getChapterList:
return new SimpleCursor(mBookshelfController.getChapterList(map));
default:
throw new IllegalStateException("Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name());
}
}
@Override
public int update(@NotNull Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Simple inner class to deliver json callback data.
*
* Only getString() makes sense.
*/
private static class SimpleCursor implements Cursor {
private String mData;
public SimpleCursor(ReturnData data) {
this.mData = new Gson().toJson(data);
}
@Override
public int getCount() {
return 1;
}
@Override
public int getPosition() {
return 0;
}
@Override
public boolean move(int i) {
return true;
}
@Override
public boolean moveToPosition(int i) {
return true;
}
@Override
public boolean moveToFirst() {
return true;
}
@Override
public boolean moveToLast() {
return true;
}
@Override
public boolean moveToNext() {
return true;
}
@Override
public boolean moveToPrevious() {
return true;
}
@Override
public boolean isFirst() {
return true;
}
@Override
public boolean isLast() {
return true;
}
@Override
public boolean isBeforeFirst() {
return false;
}
@Override
public boolean isAfterLast() {
return false;
}
@Override
public int getColumnIndex(String s) {
return 0;
}
@Override
public int getColumnIndexOrThrow(String s) throws IllegalArgumentException {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public String getColumnName(int i) {
return null;
}
@Override
public String[] getColumnNames() {
return new String[0];
}
@Override
public int getColumnCount() {
return 0;
}
@Override
public byte[] getBlob(int i) {
return new byte[0];
}
@Override
public String getString(int i) {
return mData;
}
@Override
public void copyStringToBuffer(int i, CharArrayBuffer charArrayBuffer) {
}
@Override
public short getShort(int i) {
return 0;
}
@Override
public int getInt(int i) {
return 0;
}
@Override
public long getLong(int i) {
return 0;
}
@Override
public float getFloat(int i) {
return 0;
}
@Override
public double getDouble(int i) {
return 0;
}
@Override
public int getType(int i) {
return 0;
}
@Override
public boolean isNull(int i) {
return false;
}
@Override
public void deactivate() {
}
@Override
public boolean requery() {
return false;
}
@Override
public void close() {
}
@Override
public boolean isClosed() {
return false;
}
@Override
public void registerContentObserver(ContentObserver contentObserver) {
}
@Override
public void unregisterContentObserver(ContentObserver contentObserver) {
}
@Override
public void registerDataSetObserver(DataSetObserver dataSetObserver) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
}
@Override
public void setNotificationUri(ContentResolver contentResolver, Uri uri) {
}
@Override
public Uri getNotificationUri() {
return null;
}
@Override
public boolean getWantsAllOnMoveCalls() {
return false;
}
@Override
public void setExtras(Bundle bundle) {
}
@Override
public Bundle getExtras() {
return null;
}
@Override
public Bundle respond(Bundle bundle) {
return null;
}
}
}

@ -0,0 +1,311 @@
/*
* Copyright (C) 2020 w568w
*/
package io.legado.app.api
import android.content.ContentProvider
import android.content.ContentResolver
import android.content.ContentValues
import android.content.UriMatcher
import android.database.CharArrayBuffer
import android.database.ContentObserver
import android.database.Cursor
import android.database.DataSetObserver
import android.net.Uri
import android.os.Bundle
import com.google.gson.Gson
import io.legado.app.App
import io.legado.app.web.controller.BookshelfController
import io.legado.app.web.controller.SourceController
import io.legado.app.web.utils.ReturnData
import java.util.*
/**
* Export book data to other app.
*/
class ReaderProvider : ContentProvider() {
private enum class RequestCode {
saveSource, saveSources, saveBook, deleteSources, getSource, getSources, getBookshelf, getChapterList, getBookContent
}
companion object {
const val POST_BODY_KEY = "json"
private val authority = "${App.INSTANCE.packageName}.ReaderProvider"
private val sMatcher = UriMatcher(UriMatcher.NO_MATCH)
init {
sMatcher.addURI(
authority,
"source/insert",
RequestCode.saveSource.ordinal
)
sMatcher.addURI(
authority,
"sources/insert",
RequestCode.saveSources.ordinal
)
sMatcher.addURI(
authority,
"book/insert",
RequestCode.saveBook.ordinal
)
sMatcher.addURI(
authority,
"sources/delete",
RequestCode.deleteSources.ordinal
)
sMatcher.addURI(
authority,
"source/query",
RequestCode.getSource.ordinal
)
sMatcher.addURI(
authority,
"sources/query",
RequestCode.getSources.ordinal
)
sMatcher.addURI(
authority,
"books/query",
RequestCode.getBookshelf.ordinal
)
sMatcher.addURI(
authority,
"book/chapter/query",
RequestCode.getChapterList.ordinal
)
sMatcher.addURI(
authority,
"book/content/query",
RequestCode.getBookContent.ordinal
)
}
}
override fun delete(
uri: Uri,
selection: String?,
selectionArgs: Array<String>?
): Int {
if (sMatcher.match(uri) < 0) return -1
when (RequestCode.values()[sMatcher.match(uri)]) {
RequestCode.deleteSources -> SourceController.deleteSources(selection)
else -> throw IllegalStateException(
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
)
}
return 0
}
override fun getType(uri: Uri): String? {
throw UnsupportedOperationException("Not yet implemented")
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
if (sMatcher.match(uri) < 0) return null
when (RequestCode.values()[sMatcher.match(uri)]) {
RequestCode.saveSource -> values?.let {
SourceController.saveSource(values.getAsString(POST_BODY_KEY))
}
RequestCode.saveBook -> values?.let {
BookshelfController.saveBook(values.getAsString(POST_BODY_KEY))
}
RequestCode.saveSources -> values?.let {
SourceController.saveSources(values.getAsString(POST_BODY_KEY))
}
else -> throw IllegalStateException(
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
)
}
return null
}
override fun onCreate(): Boolean {
return false
}
override fun query(
uri: Uri, projection: Array<String>?, selection: String?,
selectionArgs: Array<String>?, sortOrder: String?
): Cursor? {
val map: MutableMap<String, ArrayList<String>> = HashMap()
uri.getQueryParameter("url")?.let {
map["url"] = arrayListOf(it)
}
uri.getQueryParameter("index")?.let {
map["index"] = arrayListOf(it)
}
return if (sMatcher.match(uri) < 0) null else when (RequestCode.values()[sMatcher.match(uri)]) {
RequestCode.getSource -> SimpleCursor(SourceController.getSource(map))
RequestCode.getSources -> SimpleCursor(SourceController.sources)
RequestCode.getBookshelf -> SimpleCursor(BookshelfController.bookshelf)
RequestCode.getBookContent -> SimpleCursor(BookshelfController.getBookContent(map))
RequestCode.getChapterList -> SimpleCursor(BookshelfController.getChapterList(map))
else -> throw IllegalStateException(
"Unexpected value: " + RequestCode.values()[sMatcher.match(uri)].name
)
}
}
override fun update(
uri: Uri, values: ContentValues?, selection: String?,
selectionArgs: Array<String>?
): Int {
throw UnsupportedOperationException("Not yet implemented")
}
/**
* Simple inner class to deliver json callback data.
*
* Only getString() makes sense.
*/
private class SimpleCursor(data: ReturnData?) : Cursor {
private val mData: String = Gson().toJson(data)
override fun getCount(): Int {
return 1
}
override fun getPosition(): Int {
return 0
}
override fun move(i: Int): Boolean {
return true
}
override fun moveToPosition(i: Int): Boolean {
return true
}
override fun moveToFirst(): Boolean {
return true
}
override fun moveToLast(): Boolean {
return true
}
override fun moveToNext(): Boolean {
return true
}
override fun moveToPrevious(): Boolean {
return true
}
override fun isFirst(): Boolean {
return true
}
override fun isLast(): Boolean {
return true
}
override fun isBeforeFirst(): Boolean {
return false
}
override fun isAfterLast(): Boolean {
return false
}
override fun getColumnIndex(s: String): Int {
return 0
}
@Throws(IllegalArgumentException::class)
override fun getColumnIndexOrThrow(s: String): Int {
throw UnsupportedOperationException("Not yet implemented")
}
override fun getColumnName(i: Int): String? {
return null
}
override fun getColumnNames(): Array<String> {
return arrayOf()
}
override fun getColumnCount(): Int {
return 0
}
override fun getBlob(i: Int): ByteArray {
return ByteArray(0)
}
override fun getString(i: Int): String {
return mData
}
override fun copyStringToBuffer(
i: Int,
charArrayBuffer: CharArrayBuffer
) {
}
override fun getShort(i: Int): Short {
return 0
}
override fun getInt(i: Int): Int {
return 0
}
override fun getLong(i: Int): Long {
return 0
}
override fun getFloat(i: Int): Float {
return 0f
}
override fun getDouble(i: Int): Double {
return 0.0
}
override fun getType(i: Int): Int {
return 0
}
override fun isNull(i: Int): Boolean {
return false
}
override fun deactivate() {}
override fun requery(): Boolean {
return false
}
override fun close() {}
override fun isClosed(): Boolean {
return false
}
override fun registerContentObserver(contentObserver: ContentObserver) {}
override fun unregisterContentObserver(contentObserver: ContentObserver) {}
override fun registerDataSetObserver(dataSetObserver: DataSetObserver) {}
override fun unregisterDataSetObserver(dataSetObserver: DataSetObserver) {}
override fun setNotificationUri(contentResolver: ContentResolver, uri: Uri) {}
override fun getNotificationUri(): Uri? {
return null
}
override fun getWantsAllOnMoveCalls(): Boolean {
return false
}
override fun setExtras(bundle: Bundle) {}
override fun getExtras(): Bundle? {
return null
}
override fun respond(bundle: Bundle): Bundle? {
return null
}
}
}

@ -33,10 +33,10 @@ class HttpServer(port: Int) : NanoHTTPD(port) {
val postData = files["postData"]
when (uri) {
"/saveSource" -> returnData = SourceController().saveSource(postData)
"/saveSources" -> returnData = SourceController().saveSources(postData)
"/saveBook" -> returnData = BookshelfController().saveBook(postData)
"/deleteSources" -> returnData = SourceController().deleteSources(postData)
"/saveSource" -> returnData = SourceController.saveSource(postData)
"/saveSources" -> returnData = SourceController.saveSources(postData)
"/saveBook" -> returnData = BookshelfController.saveBook(postData)
"/deleteSources" -> returnData = SourceController.deleteSources(postData)
}
}
@ -44,13 +44,13 @@ class HttpServer(port: Int) : NanoHTTPD(port) {
val parameters = session.parameters
when (uri) {
"/getSource" -> returnData = SourceController().getSource(parameters)
"/getSources" -> returnData = SourceController().sources
"/getBookshelf" -> returnData = BookshelfController().bookshelf
"/getSource" -> returnData = SourceController.getSource(parameters)
"/getSources" -> returnData = SourceController.sources
"/getBookshelf" -> returnData = BookshelfController.bookshelf
"/getChapterList" ->
returnData = BookshelfController().getChapterList(parameters)
returnData = BookshelfController.getChapterList(parameters)
"/getBookContent" ->
returnData = BookshelfController().getBookContent(parameters)
returnData = BookshelfController.getBookContent(parameters)
}
}
}

@ -11,7 +11,7 @@ import io.legado.app.utils.getPrefInt
import io.legado.app.web.utils.ReturnData
import kotlinx.coroutines.runBlocking
class BookshelfController {
object BookshelfController {
val bookshelf: ReturnData
get() {

@ -9,7 +9,7 @@ import io.legado.app.utils.fromJsonArray
import io.legado.app.utils.fromJsonObject
import io.legado.app.web.utils.ReturnData
class SourceController {
object SourceController {
val sources: ReturnData
get() {

Loading…
Cancel
Save