android.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. import {Fragment} from 'react';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import List from 'sentry/components/list/';
  4. import ListItem from 'sentry/components/list/listItem';
  5. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  6. import type {
  7. BasePlatformOptions,
  8. Docs,
  9. DocsParams,
  10. OnboardingConfig,
  11. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  12. import {getAndroidMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  13. import {feedbackOnboardingCrashApiJava} from 'sentry/gettingStartedDocs/java/java';
  14. import {t, tct} from 'sentry/locale';
  15. import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';
  16. export enum InstallationMode {
  17. AUTO = 'auto',
  18. MANUAL = 'manual',
  19. }
  20. const platformOptions = {
  21. installationMode: {
  22. label: t('Installation Mode'),
  23. items: [
  24. {
  25. label: t('Auto'),
  26. value: InstallationMode.AUTO,
  27. },
  28. {
  29. label: t('Manual'),
  30. value: InstallationMode.MANUAL,
  31. },
  32. ],
  33. defaultValue:
  34. navigator.userAgent.indexOf('Win') !== -1
  35. ? InstallationMode.MANUAL
  36. : InstallationMode.AUTO,
  37. },
  38. } satisfies BasePlatformOptions;
  39. type PlatformOptions = typeof platformOptions;
  40. type Params = DocsParams<PlatformOptions>;
  41. const isAutoInstall = (params: Params) =>
  42. params.platformOptions.installationMode === InstallationMode.AUTO;
  43. const getManualInstallSnippet = (params: Params) => `
  44. plugins {
  45. id "com.android.application" // should be in the same module
  46. id "io.sentry.android.gradle" version "${getPackageVersion(
  47. params,
  48. 'sentry.java.android.gradle-plugin',
  49. '3.12.0'
  50. )}"
  51. }`;
  52. const getConfigurationSnippet = (params: Params) => `
  53. <application>
  54. <!-- Required: set your sentry.io project identifier (DSN) -->
  55. <meta-data android:name="io.sentry.dsn" android:value="${params.dsn}" />
  56. <!-- enable automatic breadcrumbs for user interactions (clicks, swipes, scrolls) -->
  57. <meta-data android:name="io.sentry.traces.user-interaction.enable" android:value="true" />
  58. <!-- enable screenshot for crashes -->
  59. <meta-data android:name="io.sentry.attach-screenshot" android:value="true" />
  60. <!-- enable view hierarchy for crashes -->
  61. <meta-data android:name="io.sentry.attach-view-hierarchy" android:value="true" />${
  62. params.isPerformanceSelected
  63. ? `
  64. <!-- enable the performance API by setting a sample-rate, adjust in production env -->
  65. <meta-data android:name="io.sentry.traces.sample-rate" android:value="1.0" />`
  66. : ''
  67. }${
  68. params.isProfilingSelected
  69. ? `
  70. <!-- enable profiling when starting transactions, adjust in production env -->
  71. <meta-data android:name="io.sentry.traces.profiling.sample-rate" android:value="1.0" />`
  72. : ''
  73. }
  74. </application>`;
  75. const getVerifySnippet = () => `
  76. val breakWorld = Button(this).apply {
  77. text = "Break the world"
  78. setOnClickListener {
  79. Sentry.captureException(RuntimeException("This app uses Sentry! :)"))
  80. }
  81. }
  82. addContentView(breakWorld, ViewGroup.LayoutParams(
  83. ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))`;
  84. const onboarding: OnboardingConfig<PlatformOptions> = {
  85. install: params =>
  86. isAutoInstall(params)
  87. ? [
  88. {
  89. type: StepType.INSTALL,
  90. description: tct(
  91. 'Add Sentry automatically to your app with the [wizardLink:Sentry wizard] (call this inside your project directory).',
  92. {
  93. wizardLink: (
  94. <ExternalLink href="https://docs.sentry.io/platforms/android/#install" />
  95. ),
  96. }
  97. ),
  98. configurations: [
  99. {
  100. language: 'bash',
  101. code: `brew install getsentry/tools/sentry-wizard && sentry-wizard -i android`,
  102. },
  103. {
  104. description: (
  105. <Fragment>
  106. {t('The Sentry wizard will automatically patch your application:')}
  107. <List symbol="bullet">
  108. <ListItem>
  109. {tct(
  110. "Update your app's [buildGradle:build.gradle] file with the Sentry Gradle plugin and configure it.",
  111. {
  112. buildGradle: <code />,
  113. }
  114. )}
  115. </ListItem>
  116. <ListItem>
  117. {tct(
  118. 'Update your [manifest: AndroidManifest.xml] with the default Sentry configuration',
  119. {
  120. manifest: <code />,
  121. }
  122. )}
  123. </ListItem>
  124. <ListItem>
  125. {tct(
  126. 'Create [sentryProperties: sentry.properties] with an auth token to upload proguard mappings (this file is automatically added to [gitignore: .gitignore])',
  127. {
  128. sentryProperties: <code />,
  129. gitignore: <code />,
  130. }
  131. )}
  132. </ListItem>
  133. <ListItem>
  134. {t(
  135. "Add an example error to your app's Main Activity to verify your Sentry setup"
  136. )}
  137. </ListItem>
  138. </List>
  139. <p>
  140. {tct(
  141. 'Alternatively, you can also [manualSetupLink:set up the SDK manually].',
  142. {
  143. manualSetupLink: (
  144. <ExternalLink href="https://docs.sentry.io/platforms/android/manual-setup/" />
  145. ),
  146. }
  147. )}
  148. </p>
  149. </Fragment>
  150. ),
  151. },
  152. ],
  153. },
  154. ]
  155. : [
  156. {
  157. type: StepType.INSTALL,
  158. description: tct(
  159. 'Add the [sagpLink:Sentry Android Gradle plugin] to your [app:app] module:',
  160. {
  161. sagpLink: (
  162. <ExternalLink href="https://docs.sentry.io/platforms/android/configuration/gradle/" />
  163. ),
  164. app: <code />,
  165. }
  166. ),
  167. configurations: [
  168. {
  169. language: 'groovy',
  170. partialLoading: params.sourcePackageRegistries?.isLoading,
  171. code: getManualInstallSnippet(params),
  172. },
  173. ],
  174. },
  175. ],
  176. configure: params =>
  177. isAutoInstall(params)
  178. ? []
  179. : [
  180. {
  181. type: StepType.CONFIGURE,
  182. description: (
  183. <Fragment>
  184. <p>
  185. {tct(
  186. 'Configuration is done via the application [manifest: AndroidManifest.xml]. Under the hood Sentry uses a [provider:ContentProvider] to initialize the SDK based on the values provided below. This way the SDK can capture important crashes and metrics right from the app start.',
  187. {
  188. manifest: <code />,
  189. provider: <code />,
  190. }
  191. )}
  192. </p>
  193. <p>{t("Here's an example config which should get you started:")}</p>
  194. </Fragment>
  195. ),
  196. configurations: [
  197. {
  198. language: 'xml',
  199. code: getConfigurationSnippet(params),
  200. },
  201. ],
  202. },
  203. ],
  204. verify: params =>
  205. isAutoInstall(params)
  206. ? []
  207. : [
  208. {
  209. type: StepType.VERIFY,
  210. description: tct(
  211. "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected. You can add it to your app's [mainActivity: MainActivity].",
  212. {
  213. mainActivity: <code />,
  214. }
  215. ),
  216. configurations: [
  217. {
  218. language: 'kotlin',
  219. code: getVerifySnippet(),
  220. },
  221. ],
  222. },
  223. ],
  224. nextSteps: params =>
  225. isAutoInstall(params)
  226. ? [
  227. {
  228. id: 'advanced-configuration',
  229. name: t('Advanced Configuration'),
  230. description: t('Customize the SDK initialization behavior.'),
  231. link: 'https://docs.sentry.io/platforms/android/configuration/manual-init/#manual-initialization',
  232. },
  233. {
  234. id: 'jetpack-compose',
  235. name: t('Jetpack Compose'),
  236. description: t(
  237. 'Learn about our first class integration with Jetpack Compose.'
  238. ),
  239. link: 'https://docs.sentry.io/platforms/android/configuration/integrations/jetpack-compose/',
  240. },
  241. ]
  242. : [
  243. {
  244. id: 'advanced-configuration',
  245. name: t('Advanced Configuration'),
  246. description: t('Customize the SDK initialization behavior.'),
  247. link: 'https://docs.sentry.io/platforms/android/configuration/manual-init/#manual-initialization',
  248. },
  249. {
  250. id: 'proguard-r8',
  251. name: t('ProGuard/R8'),
  252. description: t(
  253. 'Deobfuscate and get readable stacktraces in your Sentry errors.'
  254. ),
  255. link: 'https://docs.sentry.io/platforms/android/configuration/gradle/#proguardr8--dexguard',
  256. },
  257. {
  258. id: 'jetpack-compose',
  259. name: t('Jetpack Compose'),
  260. description: t(
  261. 'Learn about our first class integration with Jetpack Compose.'
  262. ),
  263. link: 'https://docs.sentry.io/platforms/android/configuration/integrations/jetpack-compose/',
  264. },
  265. {
  266. id: 'source-context',
  267. name: t('Source Context'),
  268. description: t('See your source code as part of your stacktraces in Sentry.'),
  269. link: 'https://docs.sentry.io/platforms/android/enhance-errors/source-context/',
  270. },
  271. ],
  272. };
  273. const docs: Docs<PlatformOptions> = {
  274. onboarding,
  275. feedbackOnboardingCrashApi: feedbackOnboardingCrashApiJava,
  276. crashReportOnboarding: feedbackOnboardingCrashApiJava,
  277. customMetricsOnboarding: getAndroidMetricsOnboarding(),
  278. platformOptions,
  279. };
  280. export default docs;