This is an app that uses WebView. Currently, my priority has been to get the upload done, so I haven’t organized the code yet. I’ve attempted to upload the app several times to Google Play Console for internal testing, but it keeps getting rejected due to an "intent scheme hijacking" issue.
Google only mentions that the problem lies in shouldOverrideUrlLoading, but they don’t specify exactly what the issue is. I can only find out whether the problem is resolved by submitting the app again for review.
The following code still results in the update being rejected. Which part is causing the issue?
androidManifest.xml
android:usesCleartextTraffic="false"
The code causing the issue
class CustomWebViewClientV2(val mContext:Context, val mProgress: ProgressBar, val Callback: WebCallback) : WebViewClient() {
val TAG = "CustomWebViewClientV2"
override fun shouldOverrideUrlLoading(view: WebView?, url: String): Boolean {
Log.e(TAG, "shouldOverrideUrlLoading11 $url")
return handleLoading_new(url)
}
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
Log.e(TAG, "shouldOverrideUrlLoading22")
val url = request?.url?.toString() ?: return false
return handleLoading_new(url)
}
private fun handleLoading_new(url: String): Boolean {
if (isIntent(url)) {
Log.e(TAG, "intent $url")
try {
val intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}
if (url.contains("kakaolink")) {
if (intent.resolveActivity(mContext.packageManager) != null) {
mContext.startActivity(intent)
} else {
val marketIntent = Intent(
Intent.ACTION_VIEW,
Uri.parse("market://details?id=com.kakao.talk")
).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}
mContext.startActivity(marketIntent)
}
return true
} else {
if (intent.resolveActivity(mContext.packageManager) != null) {
mContext.startActivity(intent)
return true
} else {
return false
}
}
} catch (e: Exception) {
e.printStackTrace()
return true
}
} else if (!url.startsWith("http://") && !url.startsWith("https://")) {
Log.e(TAG, "https No : $url")
try {
Intent.parseUri(url, 0).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}.run {
mContext.startActivity(this)
return true
}
} catch (e: Exception) {
return false
}
} else {
Log.e(TAG, "NO : $url")
when {
url.contains("TESTURL") || url.contains("TESTURL3")
|| url.contains("accounts.google") || url.contains("x.com") || url.contains("twitter.com") -> {
if ((url.contains("x.com") || url.contains("twitter.com")) && url.contains("TESTURL")) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
`package` = "com.twitter.android"
}
if (intent.resolveActivity(mContext.packageManager) != null) {
mContext.startActivity(intent)
} else {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}
mContext.startActivity(browserIntent)
}
}
if (url.contains("TESTURL")) {
try {
Intent.parseUri(url, 0).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}.run {
mContext.startActivity(this)
return true
}
} catch (e: Exception) {
return false
}
} else {
return false
}
}
url.contains("play.google.com/store") -> {
try {
Intent.parseUri(url, 0).apply {
setPackage("com.android.vending")
component = null
selector = null
}.run {
mContext.startActivity(this)
return true
}
} catch (e: Exception) {
return false
}
}
url.contains("TESTURL") || url.contains("link.coupang.com") -> {
try {
Intent.parseUri(url, 0).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}.run {
mContext.startActivity(this)
return true
}
} catch (e: Exception) {
return false
}
}
else -> {
return false
}
}
}
}
private fun isIntent(url: String): Boolean{
return url.startsWith("intent://")
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
if(url == null) {
Log.e(TAG, "onPageStarted url is null")
return
}
Log.e(TAG, "onPageStarted :: $url")
(mContext as Activity).runOnUiThread {
Callback.Url(false, url)
mProgress.visibility = View.VISIBLE
}
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
if(url == null){
Log.e(TAG,"onPageFinished :: url is null")
return
}
Log.e(TAG,"onPageFinished :: $url")
if(url.startsWith("market://") || url.startsWith("coupang://")){
try{
Intent.parseUri(url, 0).apply {
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null
}.run {
mContext.startActivity(this)
}
}catch (e: Exception){
e.printStackTrace()
Log.e(TAG, "onPageFinished Exception :: $e")
}
}else {
Thread {
try {
CookieManager.getInstance().flush()
}catch (e: Exception){
Log.e(TAG,"CookieManager flush error :: ${e.message}")
}
}.start()
(mContext as Activity).runOnUiThread{
Callback.Url(true, url)
mProgress.visibility = View.GONE
}
}
}
}
I resolved the issue. In the end, I replaced all uses of Intent.parseUri
with alternative code.
Unfortunately, the following solutions suggested by Google were not helpful:
addCategory(Intent.CATEGORY_BROWSABLE)
component = null
selector = null