ReaderProvider.kt 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (C) 2020 w568w
  3. */
  4. package io.legato.kazusa.api
  5. import android.content.ContentProvider
  6. import android.content.ContentValues
  7. import android.content.UriMatcher
  8. import android.database.Cursor
  9. import android.database.MatrixCursor
  10. import android.net.Uri
  11. import com.google.gson.Gson
  12. import io.legato.kazusa.api.controller.BookController
  13. import io.legato.kazusa.api.controller.BookSourceController
  14. import io.legato.kazusa.api.controller.RssSourceController
  15. import kotlinx.coroutines.runBlocking
  16. /**
  17. * Export book data to other app.
  18. */
  19. class ReaderProvider : ContentProvider() {
  20. private enum class RequestCode {
  21. SaveBookSource, SaveBookSources, DeleteBookSources, GetBookSource, GetBookSources,
  22. SaveRssSource, SaveRssSources, DeleteRssSources, GetRssSource, GetRssSources,
  23. SaveBook, GetBookshelf, RefreshToc, GetChapterList, GetBookContent, GetBookCover,
  24. SaveBookProgress
  25. }
  26. private val postBodyKey = "json"
  27. private val sMatcher by lazy {
  28. UriMatcher(UriMatcher.NO_MATCH).apply {
  29. "${context?.applicationInfo?.packageName}.readerProvider".also { authority ->
  30. addURI(authority, "bookSource/insert", RequestCode.SaveBookSource.ordinal)
  31. addURI(authority, "bookSources/insert", RequestCode.SaveBookSources.ordinal)
  32. addURI(authority, "bookSources/delete", RequestCode.DeleteBookSources.ordinal)
  33. addURI(authority, "bookSource/query", RequestCode.GetBookSource.ordinal)
  34. addURI(authority, "bookSources/query", RequestCode.GetBookSources.ordinal)
  35. addURI(authority, "rssSource/insert", RequestCode.SaveBookSource.ordinal)
  36. addURI(authority, "rssSources/insert", RequestCode.SaveBookSources.ordinal)
  37. addURI(authority, "rssSources/delete", RequestCode.DeleteBookSources.ordinal)
  38. addURI(authority, "rssSource/query", RequestCode.GetBookSource.ordinal)
  39. addURI(authority, "rssSources/query", RequestCode.GetBookSources.ordinal)
  40. addURI(authority, "book/insert", RequestCode.SaveBook.ordinal)
  41. addURI(authority, "books/query", RequestCode.GetBookshelf.ordinal)
  42. addURI(authority, "book/refreshToc/query", RequestCode.RefreshToc.ordinal)
  43. addURI(authority, "book/chapter/query", RequestCode.GetChapterList.ordinal)
  44. addURI(authority, "book/content/query", RequestCode.GetBookContent.ordinal)
  45. addURI(authority, "book/cover/query", RequestCode.GetBookCover.ordinal)
  46. }
  47. }
  48. }
  49. override fun onCreate(): Boolean {
  50. context?.let { context ->
  51. ShortCuts.buildShortCuts(context)
  52. }
  53. return false
  54. }
  55. override fun delete(
  56. uri: Uri,
  57. selection: String?,
  58. selectionArgs: Array<String>?
  59. ): Int {
  60. if (sMatcher.match(uri) < 0) return -1
  61. when (RequestCode.entries[sMatcher.match(uri)]) {
  62. RequestCode.DeleteBookSources -> BookSourceController.deleteSources(selection)
  63. RequestCode.DeleteRssSources -> BookSourceController.deleteSources(selection)
  64. else -> throw IllegalStateException(
  65. "Unexpected value: " + RequestCode.entries[sMatcher.match(uri)].name
  66. )
  67. }
  68. return 0
  69. }
  70. override fun getType(uri: Uri) = throw UnsupportedOperationException("Not yet implemented")
  71. override fun insert(uri: Uri, values: ContentValues?): Uri? {
  72. if (sMatcher.match(uri) < 0) return null
  73. runBlocking {
  74. when (RequestCode.entries[sMatcher.match(uri)]) {
  75. RequestCode.SaveBookSource -> values?.let {
  76. BookSourceController.saveSource(values.getAsString(postBodyKey))
  77. }
  78. RequestCode.SaveBookSources -> values?.let {
  79. BookSourceController.saveSources(values.getAsString(postBodyKey))
  80. }
  81. RequestCode.SaveRssSource -> values?.let {
  82. RssSourceController.saveSource(values.getAsString(postBodyKey))
  83. }
  84. RequestCode.SaveRssSources -> values?.let {
  85. RssSourceController.saveSources(values.getAsString(postBodyKey))
  86. }
  87. RequestCode.SaveBook -> values?.let {
  88. BookController.saveBook(values.getAsString(postBodyKey))
  89. }
  90. RequestCode.SaveBookProgress -> values?.let {
  91. BookController.saveBookProgress(values.getAsString(postBodyKey))
  92. }
  93. else -> throw IllegalStateException(
  94. "Unexpected value: " + RequestCode.entries[sMatcher.match(uri)].name
  95. )
  96. }
  97. }
  98. return null
  99. }
  100. override fun query(
  101. uri: Uri, projection: Array<String>?, selection: String?,
  102. selectionArgs: Array<String>?, sortOrder: String?
  103. ): Cursor? {
  104. val map: MutableMap<String, ArrayList<String>> = HashMap()
  105. uri.getQueryParameter("url")?.let {
  106. map["url"] = arrayListOf(it)
  107. }
  108. uri.getQueryParameter("index")?.let {
  109. map["index"] = arrayListOf(it)
  110. }
  111. uri.getQueryParameter("path")?.let {
  112. map["path"] = arrayListOf(it)
  113. }
  114. return if (sMatcher.match(uri) < 0) null else when (RequestCode.entries[sMatcher.match(uri)]) {
  115. RequestCode.GetBookSource -> SimpleCursor(BookSourceController.getSource(map))
  116. RequestCode.GetBookSources -> SimpleCursor(BookSourceController.sources)
  117. RequestCode.GetRssSource -> SimpleCursor(RssSourceController.getSource(map))
  118. RequestCode.GetRssSources -> SimpleCursor(RssSourceController.sources)
  119. RequestCode.GetBookshelf -> SimpleCursor(BookController.bookshelf)
  120. RequestCode.GetBookContent -> SimpleCursor(BookController.getBookContent(map))
  121. RequestCode.RefreshToc -> SimpleCursor(BookController.refreshToc(map))
  122. RequestCode.GetChapterList -> SimpleCursor(BookController.getChapterList(map))
  123. RequestCode.GetBookCover -> SimpleCursor(BookController.getCover(map))
  124. else -> throw IllegalStateException(
  125. "Unexpected value: " + RequestCode.entries[sMatcher.match(uri)].name
  126. )
  127. }
  128. }
  129. override fun update(
  130. uri: Uri, values: ContentValues?, selection: String?,
  131. selectionArgs: Array<String>?
  132. ) = throw UnsupportedOperationException("Not yet implemented")
  133. /**
  134. * Simple inner class to deliver json callback data.
  135. *
  136. * Only getString() makes sense.
  137. */
  138. private class SimpleCursor(data: ReturnData?) : MatrixCursor(arrayOf("result"), 1) {
  139. private val mData: String = Gson().toJson(data)
  140. init {
  141. addRow(arrayOf(mData))
  142. }
  143. }
  144. }