Skip to main content
GuidesAPI ReferenceExamples

Send Debug Info

Estimated reading time: 4 minutes

In this guide you will learn how to send debug info from within an app. A button to send the debug info is displayed on top of an interactive map. When the user taps the button, debug info such as the SDK version is assembled and sent.

Setup

  1. Get your Magic Lane API key token: if you do not have a token, see the Getting Started guide.
  2. Download the Maps & Navigation SDK for Android archive file.
  3. Download the SendDebugInfo project archive file or clone the project with git.
  4. See the Configure Android Example guide.

Run the example

In Android Studio, from the File menu, select Sync Project with Gradle Files.


An android device should be connected via USB cable.
Press SHIFT+F10 to compile, install and run the example on the android device.

How it works

You can open the MainActivity.kt file to see how to send debug info from within an app. In this example, a button to send the debug info is displayed on top of an interactive map.

How it works

override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
progressBar = findViewById(R.id.progressBar)
gemSurfaceView = findViewById(R.id.gem_surface)
sendDebugInfoButton = findViewById(R.id.sendDebugInfo)
progressBar.visibility = View.VISIBLE
sendDebugInfoButton.setOnClickListener {
var subject = ""
SdkCall.execute {
subject = GemSdk.sdkVersion?.let {
String.format("User feedback (SDK example) - %d.%d.%d.%d.%s", it.major, it.minor, it.year, it.week, it.revision)
} ?: "User feedback"
System.gc()
}
GEMLog.debug(this, "This is an UI message!")
sendFeedback(this, "support@magicearth.com", subject)
}
SdkSettings.onMapDataReady = {
Util.postOnMain {
progressBar.visibility = View.GONE
sendDebugInfoButton.visibility = View.VISIBLE
}
}
SdkSettings.onApiTokenRejected = {
showDialog("TOKEN REJECTED")
}
if (!Util.isInternetConnected(this))
{
showDialog("You must be connected to the internet!")
}
}

The onCreate() function is overridden in the MainActivity: AppCompatActivity() class, and checks if internet access is available, showing a dialog message if not.
findViewById() is used to obtain pointers to the various graphical user interface elements where text or graphical data is to be displayed.
A click listener is set for the button to send the debug info: sendDebugInfoButton.setOnClickListener {
A string containing the SDK version, date, and revision is created when the button is clicked by the user. The debug string is sent like this: sendFeedback(this, "support@magicearth.com", subject)
When the map is loaded, SdkSettings.onMapDataReady = { the button is made visible so the user can click on it to send the debug data: sendDebugInfoButton.visibility = View.VISIBLE.

private fun sendFeedback(a: Activity, email: String, subject: String)
{
val sendFeedbackTask = SendFeedbackTask(a, email, subject)
sendFeedbackTask.execute(null)
}

The sendFeedback() function executes the sendFeedbackTask.

private class SendFeedbackTask(val activity: Activity, val email: String, val subject: String)
: CoroutinesAsyncTask<Void, Void, Intent>()
{
override fun doInBackground(vararg params: Void?): Intent
{
val subjectText = subject
val sendIntent = Intent(Intent.ACTION_SEND_MULTIPLE)
sendIntent.type = "message/rfc822"
sendIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
sendIntent.putExtra(Intent.EXTRA_SUBJECT, subjectText)
val emailBody = "\n\n$subjectText"
sendIntent.putExtra(Intent.EXTRA_TEXT, emailBody)
var publicLogPath = ""
val privateLogPath = GemSdk.appLogPath
privateLogPath?.let {
val path = GemUtil.getApplicationPublicFilesAbsolutePath(activity, "phoneLog.txt")
if (GemUtil.copyFile(it, path))
{
publicLogPath = path
}
}
val uris = ArrayList<Uri>()
if (publicLogPath.isNotEmpty())
{
val file = File(publicLogPath)
file.deleteOnExit()
try
{
uris.add(FileProvider.getUriForFile(activity, activity.packageName + ".provider", file))
}
catch (e: Exception)
{
GEMLog.error(this, "SendFeedbackTask.doInBackground(): error = ${e.message}")
}
}
if (GemSdk.internalStoragePath.isNotEmpty())
{
val gmCrashesPath = GemSdk.internalStoragePath + File.separator + "GMcrashlogs" + File.separator + "last"
val file = File(gmCrashesPath)
if (file.exists() && file.isDirectory)
{
val files = file.listFiles()
files?.forEach breakLoop@{
try
{
uris.add(FileProvider.getUriForFile(activity, activity.packageName + ".provider", it))
}
catch (e: Exception)
{
GEMLog.error(this, "SendFeedbackTask.doInBackground(): error = ${e.message}")
}
return@breakLoop
}
}
}
sendIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
return sendIntent
}
override fun onPostExecute(result: Intent?)
{
if (result == null)
{
return
}
activity.startActivity(result)
}
}

The sendFeedbackTask class contains two overridden functions: override fun doInBackground().
This function assembles an email message containing the phone log and all the files listed in the most recent crash log, and sends it.
override fun onPostExecute()
This function restarts the app after the debug message was sent.

Android Examples

Maps SDK for Android Examples can be downloaded or cloned with Git.