android.tsx 9.9 KB

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