LeakViews.kt
TLDR
This file provides utility functions for sharing content, such as text or heap dumps, from a view in an Android application. It also includes functions for sharing content to specific platforms like Stack Overflow or GitHub issues.
Methods
share
This function allows a view to share content by creating and starting a share intent chooser.
shareHeapDump
This function allows a view to share a heap dump file by setting the file as readable, getting the content URI for the file, and starting a share intent chooser.
startShareIntentChooser
This private function starts a share intent chooser for a given content URI.
shareToStackOverflow
This function allows a view to share content to Stack Overflow by copying the content to the clipboard, showing a toast message, and opening a browser intent to the Stack Overflow page.
shareToGitHubIssue
This function allows a view to share a heap analysis failure to GitHub issues by copying the failure information to the clipboard, showing a toast message, and opening a browser intent to the GitHub new issue page.
Constants
STACKOVERFLOW_QUESTION_URL
This constant stores the URL for asking a new Stack Overflow question.
NEW_ISSUE_URL
This constant stores the URL for creating a new issue on the LeakCanary GitHub repository.
package leakcanary.internal.activity
import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.AsyncTask
import android.os.Build
import android.view.View
import android.widget.Toast
import com.squareup.leakcanary.core.BuildConfig
import com.squareup.leakcanary.core.R
import leakcanary.internal.LeakCanaryFileProvider
import leakcanary.internal.navigation.activity
import shark.HeapAnalysisFailure
import java.io.File
internal fun View.share(content: String) {
val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_TEXT, content)
activity.startActivity(
Intent.createChooser(intent, resources.getString(R.string.leak_canary_share_with))
)
}
@SuppressLint("SetWorldReadable")
internal fun View.shareHeapDump(heapDumpFile: File) {
AsyncTask.SERIAL_EXECUTOR.execute {
heapDumpFile.setReadable(true, false)
val heapDumpUri = LeakCanaryFileProvider.getUriForFile(
activity,
"com.squareup.leakcanary.fileprovider." + activity.packageName,
heapDumpFile
)
activity.runOnUiThread { startShareIntentChooser(heapDumpUri) }
}
}
private fun View.startShareIntentChooser(uri: Uri) {
val intent = Intent(Intent.ACTION_SEND)
intent.type = "application/octet-stream"
intent.putExtra(Intent.EXTRA_STREAM, uri)
activity.startActivity(
Intent.createChooser(intent, resources.getString(R.string.leak_canary_share_with))
)
}
internal fun View.shareToStackOverflow(content: String) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// AsyncTask was needed here due to setPrimaryClip making a disk write which
// violated StrictMode if on the main thread
AsyncTask.execute {
clipboard.setPrimaryClip(
ClipData.newPlainText(
context.getString(R.string.leak_canary_leak_clipdata_label),
"```\n$content```"
)
)
}
Toast.makeText(context, R.string.leak_canary_leak_copied, Toast.LENGTH_LONG)
.show()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(STACKOVERFLOW_QUESTION_URL))
try {
activity.startActivity(browserIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, R.string.leak_canary_leak_missing_browser_error, Toast.LENGTH_LONG)
.show()
}
}
internal fun View.shareToGitHubIssue(failure: HeapAnalysisFailure) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// AsyncTask was needed here due to setPrimaryClip making a disk write which
// violated StrictMode if on the main thread
AsyncTask.execute {
clipboard.setPrimaryClip(
ClipData.newPlainText(
context.getString(R.string.leak_canary_failure_clipdata_label),
"""```
|${failure.exception}
|Build.VERSION.SDK_INT: ${Build.VERSION.SDK_INT}
|Build.MANUFACTURER: ${Build.MANUFACTURER}
|LeakCanary version: ${BuildConfig.LIBRARY_VERSION}
|Analysis duration: ${failure.analysisDurationMillis} ms
|Heap dump file path: ${failure.heapDumpFile.absolutePath}
|Heap dump timestamp: ${failure.createdAtTimeMillis}
|```
""".trimMargin()
)
)
}
Toast.makeText(context, R.string.leak_canary_failure_copied, Toast.LENGTH_LONG)
.show()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(NEW_ISSUE_URL))
try {
activity.startActivity(browserIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, R.string.leak_canary_leak_missing_browser_error, Toast.LENGTH_LONG)
.show()
}
}
private const val STACKOVERFLOW_QUESTION_URL =
"http://stackoverflow.com/questions/ask?guided=false&tags=leakcanary"
private const val NEW_ISSUE_URL =
"https://github.com/square/leakcanary/issues/new?labels=type%3A+bug&template=2-bug.md"