Merge pull request #9948 from osmandapp/AddLogcatBufferTelegram
Add Logcat Buffer to Telegram Tracker
This commit is contained in:
commit
677bd5c757
11 changed files with 441 additions and 9 deletions
|
@ -20,7 +20,7 @@
|
||||||
android:screenOrientation="unspecified"
|
android:screenOrientation="unspecified"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
<activity android:name=".ui.TrackerLogcatActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MainActivity"
|
android:name=".ui.MainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
|
|
44
OsmAnd-telegram/res/layout/activity_tracker_logcat.xml
Normal file
44
OsmAnd-telegram/res/layout/activity_tracker_logcat.xml
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/app_bar_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/card_bg_color">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/action_bar_height">
|
||||||
|
|
||||||
|
<net.osmand.telegram.ui.views.TextViewEx
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/logcat_buffer"
|
||||||
|
android:textColor="@color/app_bar_title_light"
|
||||||
|
android:textSize="@dimen/title_text_size"
|
||||||
|
app:typeface="@string/font_roboto_mono_bold"/>
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/screen_bg_light"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:scrollbars="vertical" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -447,6 +447,50 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/list_item_divider"/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/card_bg_color">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/logcat_row"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<net.osmand.telegram.ui.views.TextViewEx
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingLeft="@dimen/content_padding_standard"
|
||||||
|
android:paddingRight="@dimen/content_padding_standard"
|
||||||
|
android:text="@string/logcat_buffer"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="@dimen/list_item_title_text_size"
|
||||||
|
app:firstBaselineToTopHeight="28sp"
|
||||||
|
app:typeface="@string/font_roboto_medium" />
|
||||||
|
|
||||||
|
<net.osmand.telegram.ui.views.TextViewEx
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="@dimen/content_padding_standard"
|
||||||
|
android:paddingRight="@dimen/content_padding_standard"
|
||||||
|
android:text="@string/logcat_buffer_descr"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="@dimen/list_item_description_text_size"
|
||||||
|
app:firstBaselineToTopHeight="20sp"
|
||||||
|
app:lastBaselineToBottomHeight="16sp"
|
||||||
|
app:typeface="@string/font_roboto_regular" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/card_bottom_divider"/>
|
<include layout="@layout/card_bottom_divider"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
18
OsmAnd-telegram/res/layout/item_description_long.xml
Normal file
18
OsmAnd-telegram/res/layout/item_description_long.xml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:minHeight="@dimen/list_description_height"
|
||||||
|
android:paddingLeft="@dimen/content_padding_standard"
|
||||||
|
android:paddingRight="@dimen/content_padding_standard"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:textSize="@dimen/hint_text_size"
|
||||||
|
android:linksClickable="true"
|
||||||
|
android:lineSpacingMultiplier="@dimen/text_description_line_spacing_multiplier"
|
||||||
|
tools:text="Some long description"
|
||||||
|
android:paddingEnd="@dimen/content_padding_standard"
|
||||||
|
android:paddingStart="@dimen/content_padding_standard" />
|
|
@ -27,6 +27,7 @@
|
||||||
<dimen name="dialog_welcome_title_top_margin">89dp</dimen>
|
<dimen name="dialog_welcome_title_top_margin">89dp</dimen>
|
||||||
|
|
||||||
<dimen name="list_header_height">48dp</dimen>
|
<dimen name="list_header_height">48dp</dimen>
|
||||||
|
<dimen name="list_description_height">44dp</dimen>
|
||||||
<dimen name="list_header_with_descr_height">42dp</dimen>
|
<dimen name="list_header_with_descr_height">42dp</dimen>
|
||||||
|
|
||||||
<dimen name="list_item_height">56dp</dimen>
|
<dimen name="list_item_height">56dp</dimen>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="send_report">Send report</string>
|
||||||
|
<string name="logcat_buffer_descr">Check and share detailed logs of the app</string>
|
||||||
|
<string name="logcat_buffer">Logcat buffer</string>
|
||||||
|
<string name="shared_string_export">Export</string>
|
||||||
<string name="shared_string_error_short">ERR</string>
|
<string name="shared_string_error_short">ERR</string>
|
||||||
<string name="last_update_from_telegram_date">Last update from Telegram: %1$s</string>
|
<string name="last_update_from_telegram_date">Last update from Telegram: %1$s</string>
|
||||||
<string name="last_response_date">Last response: %1$s</string>
|
<string name="last_response_date">Last response: %1$s</string>
|
||||||
|
|
|
@ -3,16 +3,20 @@ package net.osmand.telegram
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkInfo
|
import android.net.NetworkInfo
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import net.osmand.PlatformUtil
|
||||||
|
import net.osmand.telegram.ui.TrackerLogcatActivity
|
||||||
import net.osmand.telegram.helpers.*
|
import net.osmand.telegram.helpers.*
|
||||||
import net.osmand.telegram.helpers.OsmandAidlHelper.OsmandHelperListener
|
import net.osmand.telegram.helpers.OsmandAidlHelper.OsmandHelperListener
|
||||||
import net.osmand.telegram.helpers.OsmandAidlHelper.UpdatesListener
|
import net.osmand.telegram.helpers.OsmandAidlHelper.UpdatesListener
|
||||||
import net.osmand.telegram.notifications.NotificationHelper
|
import net.osmand.telegram.notifications.NotificationHelper
|
||||||
import net.osmand.telegram.utils.AndroidUtils
|
import net.osmand.telegram.utils.AndroidUtils
|
||||||
import net.osmand.telegram.utils.UiUtils
|
import net.osmand.telegram.utils.UiUtils
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class TelegramApplication : Application() {
|
class TelegramApplication : Application() {
|
||||||
|
|
||||||
|
@ -200,4 +204,33 @@ class TelegramApplication : Application() {
|
||||||
fun runInUIThread(action: (() -> Unit), delay: Long) {
|
fun runInUIThread(action: (() -> Unit), delay: Long) {
|
||||||
uiHandler.postDelayed(action, delay)
|
uiHandler.postDelayed(action, delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendCrashLog(file: File) {
|
||||||
|
val intent = Intent(Intent.ACTION_SEND)
|
||||||
|
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("crash@osmand.net"))
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(this, file))
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
intent.type = "vnd.android.cursor.dir/email"
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT, "OsmAnd bug")
|
||||||
|
val text = StringBuilder()
|
||||||
|
text.append("\nDevice : ").append(Build.DEVICE)
|
||||||
|
text.append("\nBrand : ").append(Build.BRAND)
|
||||||
|
text.append("\nModel : ").append(Build.MODEL)
|
||||||
|
text.append("\nProduct : ").append(Build.PRODUCT)
|
||||||
|
text.append("\nBuild : ").append(Build.DISPLAY)
|
||||||
|
text.append("\nVersion : ").append(Build.VERSION.RELEASE)
|
||||||
|
text.append("\nApp : ").append(getString(R.string.app_name_short))
|
||||||
|
try {
|
||||||
|
val info = packageManager.getPackageInfo(packageName, 0)
|
||||||
|
if (info != null) {
|
||||||
|
text.append("\nApk Version : ").append(info.versionName).append(" ").append(info.versionCode)
|
||||||
|
}
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
PlatformUtil.getLog(TrackerLogcatActivity::class.java).error("", e)
|
||||||
|
}
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, text.toString())
|
||||||
|
val chooserIntent = Intent.createChooser(intent, getString(R.string.send_report))
|
||||||
|
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
startActivity(chooserIntent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,14 +540,24 @@ class TelegramSettings(private val app: TelegramApplication) {
|
||||||
if (initTime && initSending) {
|
if (initTime && initSending) {
|
||||||
initializing = true
|
initializing = true
|
||||||
} else {
|
} else {
|
||||||
|
var waitingTimeError = false
|
||||||
val maxWaitingTime = WAITING_TDLIB_TIME * MAX_MESSAGES_IN_TDLIB_PER_CHAT * max(1, chatsCount)
|
val maxWaitingTime = WAITING_TDLIB_TIME * MAX_MESSAGES_IN_TDLIB_PER_CHAT * max(1, chatsCount)
|
||||||
val textSharingError = !shareInfo.lastTextMessageHandled && currentTime - shareInfo.lastSendTextMessageTime > maxWaitingTime
|
val textSharingWaitingTime = currentTime - shareInfo.lastSendTextMessageTime
|
||||||
val mapSharingError = !shareInfo.lastMapMessageHandled && currentTime - shareInfo.lastSendMapMessageTime > maxWaitingTime
|
val mapSharingWaitingTime = currentTime - shareInfo.lastSendMapMessageTime
|
||||||
if (shareInfo.hasSharingError
|
val textSharingError = !shareInfo.lastTextMessageHandled && textSharingWaitingTime > maxWaitingTime
|
||||||
|| (shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError))
|
val mapSharingError = !shareInfo.lastMapMessageHandled && mapSharingWaitingTime > maxWaitingTime
|
||||||
|| textSharingError && (shareTypeValue == SHARE_TYPE_TEXT)
|
if ((shareTypeValue == SHARE_TYPE_MAP_AND_TEXT && (textSharingError || mapSharingError))
|
||||||
|| mapSharingError && (shareTypeValue == SHARE_TYPE_MAP)
|
|| textSharingError && (shareTypeValue == SHARE_TYPE_TEXT)
|
||||||
) {
|
|| mapSharingError && (shareTypeValue == SHARE_TYPE_MAP)) {
|
||||||
|
waitingTimeError = true
|
||||||
|
log.debug("Send chats error for share type \"$shareTypeValue\"" +
|
||||||
|
"\nMax waiting time: ${maxWaitingTime}s" +
|
||||||
|
"\nLast text message handled: ${shareInfo.lastTextMessageHandled}" +
|
||||||
|
"\nText sharing waiting time: ${textSharingWaitingTime}s" +
|
||||||
|
"\nLast map message handled: ${shareInfo.lastMapMessageHandled}" +
|
||||||
|
"\nMap sharing waiting time: ${mapSharingWaitingTime}s")
|
||||||
|
}
|
||||||
|
if (shareInfo.hasSharingError || waitingTimeError) {
|
||||||
sendChatsErrors = true
|
sendChatsErrors = true
|
||||||
locationTime = max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
locationTime = max(shareInfo.lastTextSuccessfulSendTime, shareInfo.lastMapSuccessfulSendTime)
|
||||||
chatsIds.add(shareInfo.chatId)
|
chatsIds.add(shareInfo.chatId)
|
||||||
|
|
|
@ -776,6 +776,7 @@ class TelegramHelper private constructor() {
|
||||||
client?.send(TdApi.CreatePrivateChat(userId, false)) { obj ->
|
client?.send(TdApi.CreatePrivateChat(userId, false)) { obj ->
|
||||||
when (obj.constructor) {
|
when (obj.constructor) {
|
||||||
TdApi.Error.CONSTRUCTOR -> {
|
TdApi.Error.CONSTRUCTOR -> {
|
||||||
|
log.debug("createPrivateChatWithUser ERROR $obj")
|
||||||
val error = obj as TdApi.Error
|
val error = obj as TdApi.Error
|
||||||
if (error.code != IGNORED_ERROR_CODE) {
|
if (error.code != IGNORED_ERROR_CODE) {
|
||||||
shareInfo.hasSharingError = true
|
shareInfo.hasSharingError = true
|
||||||
|
@ -969,7 +970,7 @@ class TelegramHelper private constructor() {
|
||||||
val messageType = if (isBot) MESSAGE_TYPE_BOT else MESSAGE_TYPE_TEXT
|
val messageType = if (isBot) MESSAGE_TYPE_BOT else MESSAGE_TYPE_TEXT
|
||||||
when (obj.constructor) {
|
when (obj.constructor) {
|
||||||
TdApi.Error.CONSTRUCTOR -> {
|
TdApi.Error.CONSTRUCTOR -> {
|
||||||
log.debug("handleTextLocationMessageUpdate - ERROR")
|
log.debug("handleTextLocationMessageUpdate - ERROR $obj")
|
||||||
val error = obj as TdApi.Error
|
val error = obj as TdApi.Error
|
||||||
if (error.code != IGNORED_ERROR_CODE) {
|
if (error.code != IGNORED_ERROR_CODE) {
|
||||||
shareInfo.hasSharingError = true
|
shareInfo.hasSharingError = true
|
||||||
|
|
|
@ -213,6 +213,12 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
||||||
DisconnectTelegramBottomSheet.showInstance(childFragmentManager)
|
DisconnectTelegramBottomSheet.showInstance(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainView.findViewById<View>(R.id.logcat_row).setOnClickListener {
|
||||||
|
val intent = Intent(activity, TrackerLogcatActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
app.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
return mainView
|
return mainView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,271 @@
|
||||||
|
package net.osmand.telegram.ui
|
||||||
|
|
||||||
|
import android.os.AsyncTask
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.*
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import net.osmand.PlatformUtil
|
||||||
|
import net.osmand.telegram.R
|
||||||
|
import net.osmand.telegram.TelegramApplication
|
||||||
|
import java.io.*
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TrackerLogcatActivity : AppCompatActivity() {
|
||||||
|
private var logcatAsyncTask: LogcatAsyncTask? = null
|
||||||
|
private val logs: MutableList<String> = ArrayList()
|
||||||
|
private var adapter: LogcatAdapter? = null
|
||||||
|
private val LEVELS = arrayOf("D", "I", "W", "E")
|
||||||
|
private var filterLevel = 1
|
||||||
|
private lateinit var recyclerView: RecyclerView
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
val app: TelegramApplication = getApplication() as TelegramApplication
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_tracker_logcat)
|
||||||
|
|
||||||
|
val toolbar = findViewById<Toolbar>(R.id.toolbar).apply {
|
||||||
|
navigationIcon = app.uiUtils.getThemedIcon(R.drawable.ic_arrow_back)
|
||||||
|
setNavigationOnClickListener { onBackPressed() }
|
||||||
|
}
|
||||||
|
setSupportActionBar(toolbar)
|
||||||
|
setupIntermediateProgressBar()
|
||||||
|
|
||||||
|
adapter = LogcatAdapter()
|
||||||
|
recyclerView = findViewById<View>(R.id.recycler_view) as RecyclerView
|
||||||
|
recyclerView!!.layoutManager = LinearLayoutManager(this)
|
||||||
|
recyclerView!!.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun setupIntermediateProgressBar() {
|
||||||
|
val progressBar = ProgressBar(this)
|
||||||
|
progressBar.visibility = View.GONE
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
val supportActionBar = supportActionBar
|
||||||
|
if (supportActionBar != null) {
|
||||||
|
supportActionBar.setDisplayShowCustomEnabled(true)
|
||||||
|
supportActionBar.customView = progressBar
|
||||||
|
setSupportProgressBarIndeterminateVisibility(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setSupportProgressBarIndeterminateVisibility(visible: Boolean) {
|
||||||
|
val supportActionBar = supportActionBar
|
||||||
|
if (supportActionBar != null) {
|
||||||
|
supportActionBar.customView.visibility = if (visible) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
startLogcatAsyncTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
stopLogcatAsyncTask()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
val app: TelegramApplication = applicationContext as TelegramApplication
|
||||||
|
val share: MenuItem = menu.add(0, SHARE_ID, 0, R.string.shared_string_export)
|
||||||
|
share.icon = app.uiUtils.getThemedIcon(R.drawable.ic_action_share)
|
||||||
|
share.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
||||||
|
val level = menu.add(0, LEVEL_ID, 0, "")
|
||||||
|
level.title = getFilterLevel()
|
||||||
|
level.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
||||||
|
return super.onCreateOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFilterLevel(): String {
|
||||||
|
return "*:" + LEVELS[filterLevel]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
val itemId = item.itemId
|
||||||
|
when (itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
LEVEL_ID -> {
|
||||||
|
filterLevel++
|
||||||
|
if (filterLevel >= LEVELS.size) {
|
||||||
|
filterLevel = 0
|
||||||
|
}
|
||||||
|
item.title = getFilterLevel()
|
||||||
|
stopLogcatAsyncTask()
|
||||||
|
logs.clear()
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
startLogcatAsyncTask()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
SHARE_ID -> {
|
||||||
|
startSaveLogsAsyncTask()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startSaveLogsAsyncTask() {
|
||||||
|
val saveLogsAsyncTask = SaveLogsAsyncTask(this, logs)
|
||||||
|
saveLogsAsyncTask.execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startLogcatAsyncTask() {
|
||||||
|
logcatAsyncTask = LogcatAsyncTask(this, getFilterLevel())
|
||||||
|
logcatAsyncTask!!.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopLogcatAsyncTask() {
|
||||||
|
if (logcatAsyncTask != null && logcatAsyncTask!!.status == AsyncTask.Status.RUNNING) {
|
||||||
|
logcatAsyncTask!!.cancel(false)
|
||||||
|
logcatAsyncTask!!.stopLogging()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class LogcatAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
val inflater = LayoutInflater.from(viewGroup.context)
|
||||||
|
val itemView = inflater.inflate(R.layout.item_description_long, viewGroup, false) as TextView
|
||||||
|
itemView.gravity = Gravity.CENTER_VERTICAL
|
||||||
|
return LogViewHolder(itemView)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
if (holder is LogViewHolder) {
|
||||||
|
val log = getLog(position)
|
||||||
|
holder.logTextView.text = log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return logs.size
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLog(position: Int): String {
|
||||||
|
return logs[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class LogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val logTextView: TextView = itemView.findViewById(R.id.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SaveLogsAsyncTask internal constructor(logcatActivity: TrackerLogcatActivity, logs: Collection<String>) : AsyncTask<Void?, String?, File?>() {
|
||||||
|
private val logcatActivity: WeakReference<TrackerLogcatActivity>
|
||||||
|
private val logs: Collection<String>
|
||||||
|
|
||||||
|
override fun onPreExecute() {
|
||||||
|
val activity = logcatActivity.get()
|
||||||
|
activity?.setSupportProgressBarIndeterminateVisibility(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doInBackground(vararg voids: Void?): File {
|
||||||
|
val app: TelegramApplication = logcatActivity.get()?.applicationContext as TelegramApplication
|
||||||
|
val file = File(app.getExternalFilesDir(null), LOGCAT_PATH)
|
||||||
|
try {
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete()
|
||||||
|
}
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
for (log in logs) {
|
||||||
|
stringBuilder.append(log)
|
||||||
|
stringBuilder.append("\n")
|
||||||
|
}
|
||||||
|
if (file.parentFile.canWrite()) {
|
||||||
|
val writer = BufferedWriter(FileWriter(file, true))
|
||||||
|
writer.write(stringBuilder.toString())
|
||||||
|
writer.close()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.error(e)
|
||||||
|
}
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPostExecute(file: File?) {
|
||||||
|
val activity = logcatActivity.get()
|
||||||
|
if (activity != null && file != null) {
|
||||||
|
val app: TelegramApplication = activity.applicationContext as TelegramApplication
|
||||||
|
activity.setSupportProgressBarIndeterminateVisibility(false)
|
||||||
|
app.sendCrashLog(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.logcatActivity = WeakReference(logcatActivity)
|
||||||
|
this.logs = logs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogcatAsyncTask internal constructor(logcatActivity: TrackerLogcatActivity?, filterLevel: String) : AsyncTask<Void?, String?, Void?>() {
|
||||||
|
private var processLogcat: Process? = null
|
||||||
|
private val logcatActivity: WeakReference<TrackerLogcatActivity?>
|
||||||
|
private val filterLevel: String
|
||||||
|
|
||||||
|
override fun doInBackground(vararg voids: Void?): Void? {
|
||||||
|
try {
|
||||||
|
val filter = android.os.Process.myPid().toString()
|
||||||
|
val command = arrayOf("logcat", filterLevel, "--pid=$filter", "-T", MAX_BUFFER_LOG.toString())
|
||||||
|
processLogcat = Runtime.getRuntime().exec(command)
|
||||||
|
val bufferedReader = BufferedReader(InputStreamReader(processLogcat?.inputStream))
|
||||||
|
var line: String?
|
||||||
|
while (bufferedReader.readLine().also { line = it } != null && logcatActivity.get() != null) {
|
||||||
|
if (isCancelled) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
publishProgress(line)
|
||||||
|
}
|
||||||
|
stopLogging()
|
||||||
|
} catch (e: IOException) { // ignore
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log.error(e)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProgressUpdate(vararg values: String?) {
|
||||||
|
if (values.size > 0 && !isCancelled) {
|
||||||
|
val activity = logcatActivity.get()
|
||||||
|
if (activity != null) {
|
||||||
|
val autoscroll = !activity.recyclerView!!.canScrollVertically(1)
|
||||||
|
for (s in values) {
|
||||||
|
if (s != null) {
|
||||||
|
activity.logs.add(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activity.adapter!!.notifyDataSetChanged()
|
||||||
|
if (autoscroll) {
|
||||||
|
activity.recyclerView!!.scrollToPosition(activity.logs.size - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopLogging() {
|
||||||
|
if (processLogcat != null) {
|
||||||
|
processLogcat!!.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.logcatActivity = WeakReference(logcatActivity)
|
||||||
|
this.filterLevel = filterLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val LOGCAT_PATH = "logcat.log"
|
||||||
|
private const val MAX_BUFFER_LOG = 10000
|
||||||
|
private const val SHARE_ID = 0
|
||||||
|
private const val LEVEL_ID = 1
|
||||||
|
private val log = PlatformUtil.getLog(TrackerLogcatActivity::class.java)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue