android.tsx 10 KB

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