android / android/nowinandroid
[Bug]: launchCustomChromeTab should handle ActivityNotFoundException
- Dominant language
- Kotlin
- Stars
- 21.8k
- Forks
- 4.6k
- Avg merge
- 19h 20m
- Merged PRs (30d)
- 2
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Is there a StackOverflow question about this issue?
- [X] I have searched StackOverflow
### What happened?
If you run NIA on a device without a browser installed, tapping on an item will crash the app with `ActivityNotFoundException` as it cannot find an activity to handle the view intent.
This is very rare, but we should fix this as a best practice and ideally show an error. At least, we should catch the exception so the app doesn't crash.
### Relevant logcat output
```shell
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=https://android-developers.googleblog.com/... (has extras) }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2161)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1805)
at android.app.Activity.startActivityForResult(Activity.java:5470)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:780)
at android.app.Activity.startActivityForResult(Activity.java:5428)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:761)
at android.app.Activity.startActivity(Activity.java:5926)
at androidx.core.content.ContextCompat$Api16Impl.startActivity(ContextCompat.java:1064)
at androidx.core.content.ContextCompat.startActivity(ContextCompat.java:322)
at androidx.browser.customtabs.CustomTabsIntent.launchUrl(CustomTabsIntent.java:478)
at com.google.samples.apps.nowinandroid.core.ui.NewsFeedKt.launchCustomChromeTab(NewsFeed.kt:114)
at com.google.samples.apps.nowinandroid.core.ui.NewsFeedKt$newsFeed$4$2.invoke(NewsFeed.kt:86)
at com.google.samples.apps.nowinandroid.core.ui.NewsFeedKt$newsFeed$4$2.invoke(NewsFeed.kt:78)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke-k-4lQ0M(Clickable.kt:895)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke(Clickable.kt:889)
at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1.invokeSuspend(TapGestureDetector.kt:255)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:665)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent(SuspendingPointerInputFilter.kt:544)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:566)
at androidx.compose.foundation.AbstractClickablePointerInputNode.onPointerEvent-H0pRuoY(Clickable.kt:855)
at androidx.compose.foundation.AbstractClickableNode.onPointerEvent-H0pRuoY(Clickable.kt:703)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:317)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:183)
at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:102)
at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:96)
```
### Code of Conduct
- [X] I agree to follow this project's Code of Conduct
Contributor guide
Research direction
Start in NewsFeed.kt at launchCustomChromeTab, identified by the stack trace at line 114, and inspect how the custom tab launch is triggered from the news feed. Reproduce the missing-browser case if possible and verify that tapping an item no longer crashes with ActivityNotFoundException; the issue suggests showing an error, or at minimum preventing the crash.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100