Use MangaPlus JSON API instead of Protobuf. (#11326)
This commit is contained in:
parent
29707fe4fd
commit
88fc45c2d1
|
@ -22,6 +22,14 @@
|
||||||
android:host="www.mangaplus.shueisha.co.jp"
|
android:host="www.mangaplus.shueisha.co.jp"
|
||||||
android:pathPattern="/titles/..*"
|
android:pathPattern="/titles/..*"
|
||||||
android:scheme="https" />
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="jumpg-webapi.tokyo-cdn.com"
|
||||||
|
android:path="/www/sns_share"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="www.jumpg-webapi.tokyo-cdn.com"
|
||||||
|
android:path="/www/sns_share"
|
||||||
|
android:scheme="https" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'MANGA Plus by SHUEISHA'
|
extName = 'MANGA Plus by SHUEISHA'
|
||||||
pkgNameSuffix = 'all.mangaplus'
|
pkgNameSuffix = 'all.mangaplus'
|
||||||
extClass = '.MangaPlusFactory'
|
extClass = '.MangaPlusFactory'
|
||||||
extVersionCode = 28
|
extVersionCode = 29
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -15,8 +15,8 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import kotlinx.serialization.decodeFromByteArray
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
@ -29,6 +29,7 @@ import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
abstract class MangaPlus(
|
abstract class MangaPlus(
|
||||||
|
@ -56,6 +57,8 @@ abstract class MangaPlus(
|
||||||
.addInterceptor(SpecificHostRateLimitInterceptor(baseUrl.toHttpUrl(), 2))
|
.addInterceptor(SpecificHostRateLimitInterceptor(baseUrl.toHttpUrl(), 2))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences by lazy {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
}
|
}
|
||||||
|
@ -73,11 +76,11 @@ abstract class MangaPlus(
|
||||||
.set("Referer", "$baseUrl/manga_list/hot")
|
.set("Referer", "$baseUrl/manga_list/hot")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$API_URL/title_list/ranking", newHeaders)
|
return GET("$API_URL/title_list/ranking?format=json", newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
@ -101,17 +104,18 @@ abstract class MangaPlus(
|
||||||
.set("Referer", "$baseUrl/updates")
|
.set("Referer", "$baseUrl/updates")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$API_URL/web/web_homeV3?lang=$internalLang", newHeaders)
|
return GET("$API_URL/web/web_homeV3?lang=$internalLang&format=json", newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
|
||||||
// Fetch all titles to get newer thumbnail URLs in the interceptor.
|
// Fetch all titles to get newer thumbnail URLs in the interceptor.
|
||||||
val popularResponse = client.newCall(popularMangaRequest(1)).execute().asProto()
|
val popularResponse = client.newCall(popularMangaRequest(1)).execute()
|
||||||
|
.asMangaPlusResponse()
|
||||||
|
|
||||||
if (popularResponse.success != null) {
|
if (popularResponse.success != null) {
|
||||||
titleList = popularResponse.success.titleRankingView!!.titles
|
titleList = popularResponse.success.titleRankingView!!.titles
|
||||||
|
@ -143,7 +147,7 @@ abstract class MangaPlus(
|
||||||
}
|
}
|
||||||
|
|
||||||
val filteredResult = it.mangas.filter { manga ->
|
val filteredResult = it.mangas.filter { manga ->
|
||||||
manga.title.contains(query, true)
|
manga.title.contains(query.trim(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
MangasPage(filteredResult, it.hasNextPage)
|
MangasPage(filteredResult, it.hasNextPage)
|
||||||
|
@ -159,11 +163,11 @@ abstract class MangaPlus(
|
||||||
.set("Referer", "$baseUrl/manga_list/all")
|
.set("Referer", "$baseUrl/manga_list/all")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$API_URL/title_list/allV2", newHeaders)
|
return GET("$API_URL/title_list/allV2?format=json", newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
@ -206,7 +210,7 @@ abstract class MangaPlus(
|
||||||
.set("Referer", "$baseUrl/titles/$titleId")
|
.set("Referer", "$baseUrl/titles/$titleId")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET("$API_URL/title_detail?title_id=$titleId", newHeaders)
|
return GET("$API_URL/title_detail?title_id=$titleId&format=json", newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround to allow "Open in browser" use the real URL.
|
// Workaround to allow "Open in browser" use the real URL.
|
||||||
|
@ -224,7 +228,7 @@ abstract class MangaPlus(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
@ -245,7 +249,7 @@ abstract class MangaPlus(
|
||||||
override fun chapterListRequest(manga: SManga): Request = titleDetailsRequest(manga.url)
|
override fun chapterListRequest(manga: SManga): Request = titleDetailsRequest(manga.url)
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
@ -278,13 +282,14 @@ abstract class MangaPlus(
|
||||||
.addQueryParameter("chapter_id", chapterId)
|
.addQueryParameter("chapter_id", chapterId)
|
||||||
.addQueryParameter("split", if (splitImages) "yes" else "no")
|
.addQueryParameter("split", if (splitImages) "yes" else "no")
|
||||||
.addQueryParameter("img_quality", imageQuality)
|
.addQueryParameter("img_quality", imageQuality)
|
||||||
|
.addQueryParameter("format", "json")
|
||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
return GET(url, newHeaders)
|
return GET(url, newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val result = response.asProto()
|
val result = response.asMangaPlusResponse()
|
||||||
|
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
@ -292,7 +297,7 @@ abstract class MangaPlus(
|
||||||
val referer = response.request.header("Referer")!!
|
val referer = response.request.header("Referer")!!
|
||||||
|
|
||||||
return result.success.mangaViewer!!.pages
|
return result.success.mangaViewer!!.pages
|
||||||
.mapNotNull(MangaPlusPage::page)
|
.mapNotNull(MangaPlusPage::mangaPage)
|
||||||
.mapIndexed { i, page ->
|
.mapIndexed { i, page ->
|
||||||
val encryptionKey = if (page.encryptionKey == null) "" else
|
val encryptionKey = if (page.encryptionKey == null) "" else
|
||||||
"&encryptionKey=${page.encryptionKey}"
|
"&encryptionKey=${page.encryptionKey}"
|
||||||
|
@ -418,8 +423,8 @@ abstract class MangaPlus(
|
||||||
else -> englishPopup
|
else -> englishPopup
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Response.asProto(): MangaPlusResponse = use {
|
private fun Response.asMangaPlusResponse(): MangaPlusResponse = use {
|
||||||
ProtoBuf.decodeFromByteArray(body!!.bytes())
|
json.decodeFromString(body!!.string())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1,66 +1,66 @@
|
||||||
package eu.kanade.tachiyomi.extension.all.mangaplus
|
package eu.kanade.tachiyomi.extension.all.mangaplus
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MangaPlusResponse(
|
data class MangaPlusResponse(
|
||||||
@ProtoNumber(1) val success: SuccessResult? = null,
|
val success: SuccessResult? = null,
|
||||||
@ProtoNumber(2) val error: ErrorResult? = null
|
val error: ErrorResult? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ErrorResult(
|
data class ErrorResult(
|
||||||
@ProtoNumber(2) val englishPopup: Popup,
|
val englishPopup: Popup,
|
||||||
@ProtoNumber(3) val spanishPopup: Popup
|
val spanishPopup: Popup
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Popup(
|
data class Popup(
|
||||||
@ProtoNumber(1) val subject: String,
|
val subject: String,
|
||||||
@ProtoNumber(2) val body: String
|
val body: String
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SuccessResult(
|
data class SuccessResult(
|
||||||
@ProtoNumber(1) val isFeaturedUpdated: Boolean? = false,
|
val isFeaturedUpdated: Boolean? = false,
|
||||||
@ProtoNumber(6) val titleRankingView: TitleRankingView? = null,
|
val titleRankingView: TitleRankingView? = null,
|
||||||
@ProtoNumber(8) val titleDetailView: TitleDetailView? = null,
|
val titleDetailView: TitleDetailView? = null,
|
||||||
@ProtoNumber(10) val mangaViewer: MangaViewer? = null,
|
val mangaViewer: MangaViewer? = null,
|
||||||
@ProtoNumber(25) val allTitlesViewV2: AllTitlesViewV2? = null,
|
val allTitlesViewV2: AllTitlesViewV2? = null,
|
||||||
@ProtoNumber(31) val webHomeViewV3: WebHomeViewV3? = null
|
val webHomeViewV3: WebHomeViewV3? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TitleRankingView(@ProtoNumber(1) val titles: List<Title> = emptyList())
|
data class TitleRankingView(val titles: List<Title> = emptyList())
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AllTitlesViewV2(
|
data class AllTitlesViewV2(
|
||||||
@ProtoNumber(1) val allTitlesGroup: List<AllTitlesGroup> = emptyList()
|
@SerialName("AllTitlesGroup") val allTitlesGroup: List<AllTitlesGroup> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AllTitlesGroup(
|
data class AllTitlesGroup(
|
||||||
@ProtoNumber(1) val theTitle: String,
|
val theTitle: String,
|
||||||
@ProtoNumber(2) val titles: List<Title> = emptyList()
|
val titles: List<Title> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class WebHomeViewV3(@ProtoNumber(2) val groups: List<UpdatedTitleV2Group> = emptyList())
|
data class WebHomeViewV3(val groups: List<UpdatedTitleV2Group> = emptyList())
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TitleDetailView(
|
data class TitleDetailView(
|
||||||
@ProtoNumber(1) val title: Title,
|
val title: Title,
|
||||||
@ProtoNumber(2) val titleImageUrl: String,
|
val titleImageUrl: String,
|
||||||
@ProtoNumber(3) val overview: String,
|
val overview: String,
|
||||||
@ProtoNumber(4) val backgroundImageUrl: String,
|
val backgroundImageUrl: String,
|
||||||
@ProtoNumber(5) val nextTimeStamp: Int = 0,
|
val nextTimeStamp: Int = 0,
|
||||||
@ProtoNumber(7) val viewingPeriodDescription: String = "",
|
val viewingPeriodDescription: String = "",
|
||||||
@ProtoNumber(8) val nonAppearanceInfo: String = "",
|
val nonAppearanceInfo: String = "",
|
||||||
@ProtoNumber(9) val firstChapterList: List<Chapter> = emptyList(),
|
val firstChapterList: List<Chapter> = emptyList(),
|
||||||
@ProtoNumber(10) val lastChapterList: List<Chapter> = emptyList(),
|
val lastChapterList: List<Chapter> = emptyList(),
|
||||||
@ProtoNumber(14) val isSimulReleased: Boolean = false,
|
val isSimulReleased: Boolean = false,
|
||||||
@ProtoNumber(17) val chaptersDescending: Boolean = true
|
val chaptersDescending: Boolean = true
|
||||||
) {
|
) {
|
||||||
private val isWebtoon: Boolean
|
private val isWebtoon: Boolean
|
||||||
get() = firstChapterList.all(Chapter::isVerticalOnly) &&
|
get() = firstChapterList.all(Chapter::isVerticalOnly) &&
|
||||||
|
@ -89,76 +89,62 @@ data class TitleDetailView(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MangaViewer(@ProtoNumber(1) val pages: List<MangaPlusPage> = emptyList())
|
data class MangaViewer(val pages: List<MangaPlusPage> = emptyList())
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Title(
|
data class Title(
|
||||||
@ProtoNumber(1) val titleId: Int,
|
val titleId: Int,
|
||||||
@ProtoNumber(2) val name: String,
|
val name: String,
|
||||||
@ProtoNumber(3) val author: String,
|
val author: String,
|
||||||
@ProtoNumber(4) val portraitImageUrl: String,
|
val portraitImageUrl: String,
|
||||||
@ProtoNumber(5) val landscapeImageUrl: String,
|
val landscapeImageUrl: String,
|
||||||
@ProtoNumber(6) val viewCount: Int = 0,
|
val viewCount: Int = 0,
|
||||||
@ProtoNumber(7) val language: Language? = Language.ENGLISH
|
val language: Language? = Language.ENGLISH
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
enum class Language {
|
||||||
enum class Language(val id: Int) {
|
ENGLISH,
|
||||||
@ProtoNumber(0)
|
SPANISH,
|
||||||
ENGLISH(0),
|
FRENCH,
|
||||||
|
INDONESIAN,
|
||||||
@ProtoNumber(1)
|
PORTUGUESE_BR,
|
||||||
SPANISH(1),
|
RUSSIAN,
|
||||||
|
THAI
|
||||||
@ProtoNumber(2)
|
|
||||||
FRENCH(2),
|
|
||||||
|
|
||||||
@ProtoNumber(3)
|
|
||||||
INDONESIAN(4),
|
|
||||||
|
|
||||||
@ProtoNumber(4)
|
|
||||||
PORTUGUESE_BR(4),
|
|
||||||
|
|
||||||
@ProtoNumber(5)
|
|
||||||
RUSSIAN(5),
|
|
||||||
|
|
||||||
@ProtoNumber(6)
|
|
||||||
THAI(6)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class UpdatedTitleV2Group(
|
data class UpdatedTitleV2Group(
|
||||||
@ProtoNumber(1) val groupName: String,
|
val groupName: String,
|
||||||
@ProtoNumber(2) val titleGroups: List<OriginalTitleGroup> = emptyList()
|
val titleGroups: List<OriginalTitleGroup> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class OriginalTitleGroup(
|
data class OriginalTitleGroup(
|
||||||
@ProtoNumber(1) val theTitle: String,
|
val theTitle: String,
|
||||||
@ProtoNumber(3) val titles: List<UpdatedTitle> = emptyList()
|
val titles: List<UpdatedTitle> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class UpdatedTitle(@ProtoNumber(1) val title: Title)
|
data class UpdatedTitle(val title: Title)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Chapter(
|
data class Chapter(
|
||||||
@ProtoNumber(1) val titleId: Int,
|
val titleId: Int,
|
||||||
@ProtoNumber(2) val chapterId: Int,
|
val chapterId: Int,
|
||||||
@ProtoNumber(3) val name: String,
|
val name: String,
|
||||||
@ProtoNumber(4) val subTitle: String? = null,
|
val subTitle: String? = null,
|
||||||
@ProtoNumber(6) val startTimeStamp: Int,
|
val startTimeStamp: Int,
|
||||||
@ProtoNumber(7) val endTimeStamp: Int,
|
val endTimeStamp: Int,
|
||||||
@ProtoNumber(9) val isVerticalOnly: Boolean = false
|
val isVerticalOnly: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MangaPlusPage(@ProtoNumber(1) val page: MangaPage? = null)
|
data class MangaPlusPage(val mangaPage: MangaPage? = null)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MangaPage(
|
data class MangaPage(
|
||||||
@ProtoNumber(1) val imageUrl: String,
|
val imageUrl: String,
|
||||||
@ProtoNumber(2) val width: Int,
|
val width: Int,
|
||||||
@ProtoNumber(3) val height: Int,
|
val height: Int,
|
||||||
@ProtoNumber(5) val encryptionKey: String? = null
|
val encryptionKey: String? = null
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,18 +14,23 @@ class MangaPlusUrlActivity : Activity() {
|
||||||
|
|
||||||
val pathSegments = intent?.data?.pathSegments
|
val pathSegments = intent?.data?.pathSegments
|
||||||
if (pathSegments != null && pathSegments.size > 1) {
|
if (pathSegments != null && pathSegments.size > 1) {
|
||||||
val titleId = pathSegments[1]
|
val titleId = if (!pathSegments[1].equals("sns_share")) pathSegments[1] else
|
||||||
|
intent?.data?.getQueryParameter("title_id")
|
||||||
|
|
||||||
val mainIntent = Intent().apply {
|
if (titleId != null) {
|
||||||
action = "eu.kanade.tachiyomi.SEARCH"
|
val mainIntent = Intent().apply {
|
||||||
putExtra("query", MangaPlus.PREFIX_ID_SEARCH + titleId)
|
action = "eu.kanade.tachiyomi.SEARCH"
|
||||||
putExtra("filter", packageName)
|
putExtra("query", MangaPlus.PREFIX_ID_SEARCH + titleId)
|
||||||
}
|
putExtra("filter", packageName)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
startActivity(mainIntent)
|
startActivity(mainIntent)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
Log.e("MangaPlusUrlActivity", e.toString())
|
Log.e("MangaPlusUrlActivity", e.toString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e("MangaPlusUrlActivity", "Missing title ID from the URL")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e("MangaPlusUrlActivity", "Could not parse URI from intent $intent")
|
Log.e("MangaPlusUrlActivity", "Could not parse URI from intent $intent")
|
||||||
|
|
Loading…
Reference in New Issue