android / android/nowinandroid

[Bug]: launchCustomChromeTab should handle ActivityNotFoundException

Open
#1,068 2 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.