Browse Source

Remove the SendCrashActivity

merge-requests/2174/head
Nicolas Pomepuy 1 year ago
parent
commit
3018dbcc3e
  1. 4
      application/app/src/main/java/org/videolan/mobile/app/AppSetupDelegate.kt
  2. 15
      application/vlc-android/AndroidManifest.xml
  3. 163
      application/vlc-android/res/layout/send_crash_activity.xml
  4. 63
      application/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
  5. 212
      application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt

4
application/app/src/main/java/org/videolan/mobile/app/AppSetupDelegate.kt

@ -26,7 +26,6 @@ import android.app.Application.ActivityLifecycleCallbacks
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import kotlinx.coroutines.DEBUG_PROPERTY_NAME
@ -51,7 +50,6 @@ import org.videolan.tools.AppScope
import org.videolan.tools.KEY_ENABLE_REMOTE_ACCESS
import org.videolan.tools.Settings
import org.videolan.vlc.BuildConfig
import org.videolan.vlc.gui.SendCrashActivity
import org.videolan.vlc.gui.helpers.NotificationHelper
import org.videolan.vlc.util.DialogDelegate
import org.videolan.vlc.util.NetworkConnectionManager
@ -121,8 +119,6 @@ class AppSetupDelegate : AppDelegate,
if (!VLCInstance.testCompatibleCPU(AppContextProvider.appContext)) return@innerLaunch
Dialog.setCallbacks(VLCInstance.getInstance(this@backgroundInit), DialogDelegate)
}
packageManager.setComponentEnabledSetting(ComponentName(this@backgroundInit, SendCrashActivity::class.java),
if (BuildConfig.BETA) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
if (!AndroidDevices.isAndroidTv) sendBroadcast(Intent(MiniPlayerAppWidgetProvider.ACTION_WIDGET_INIT).apply {
component = ComponentName(appContextProvider.appContext, MiniPlayerAppWidgetProvider::class.java)
})

15
application/vlc-android/AndroidManifest.xml

@ -994,21 +994,6 @@
android:name=".gui.SearchActivity"
android:theme="@style/Theme.VLC"
android:windowSoftInputMode="stateVisible" />
<activity
android:name=".gui.SendCrashActivity"
android:label="@string/vlc_reporter"
android:theme="@style/Theme.VLC.SendCrashDialog"
android:icon="@mipmap/ic_launcher_reporter"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:exported="true"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".gui.BetaWelcomeActivity"
android:theme="@style/Theme.VLC.SendCrashDialog"/>

163
application/vlc-android/res/layout/send_crash_activity.xml

@ -1,163 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data></data>
<androidx.constraintlayout.widget.ConstraintLayout
android:orientation="vertical"
android:layout_width="300dp"
android:layout_height="wrap_content">
<TextView
android:text="@string/send_crash_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textView15"
app:layout_constraintTop_toTopOf="@+id/imageView5"
app:layout_constraintBottom_toBottomOf="@+id/imageView5"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toEndOf="@+id/imageView5"
android:layout_marginStart="8dp"
android:textSize="18sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_stat_vlc"
android:id="@+id/imageView5"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintHorizontal_chainStyle="packed" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView15"
android:layout_marginTop="16dp"
android:id="@+id/crashFirstStepContainer"
tools:visibility="gone">
<TextView
android:text="@string/send_crash_action_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textView21"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
<Button
android:text="@string/report_a_bug"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/reportBugButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:layout_constraintTop_toBottomOf="@+id/textView21"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="24dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
<Button
android:text="@string/report_a_crash"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/reportCrashButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:layout_constraintTop_toBottomOf="@+id/reportBugButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/textView15"
android:id="@+id/crashSecondStepContainer"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:text="@string/send_crash_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textView18"
android:layout_marginTop="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp" />
<TextView
android:text="@string/send_crash_warning"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/textView19"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/textView18"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp" />
<Switch
android:text="@string/include_medialib"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/includeMedialibSwitch"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/textView19"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="16dp" />
<Button
android:text="@string/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/send_crash_button"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@+id/includeMedialibSwitch"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" />
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/sendCrashProgress"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@+id/includeMedialibSwitch"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

63
application/vlc-android/src/org/videolan/vlc/MediaParsingService.kt

@ -38,30 +38,63 @@ import android.os.PowerManager
import android.util.Log
import androidx.core.content.getSystemService
import androidx.core.net.toUri
import androidx.lifecycle.*
import kotlinx.coroutines.*
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleService
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ServiceLifecycleDispatcher
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.channels.ActorScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.videolan.libvlc.LibVLC
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.MLServiceLocator
import org.videolan.medialibrary.interfaces.DevicesDiscoveryCb
import org.videolan.medialibrary.interfaces.Medialibrary
import org.videolan.medialibrary.stubs.StubMedialibrary
import org.videolan.resources.*
import org.videolan.resources.ACTION_CHECK_STORAGES
import org.videolan.resources.ACTION_CONTENT_INDEXING
import org.videolan.resources.ACTION_DISCOVER
import org.videolan.resources.ACTION_DISCOVER_DEVICE
import org.videolan.resources.ACTION_FORCE_RELOAD
import org.videolan.resources.ACTION_INIT
import org.videolan.resources.ACTION_PAUSE_SCAN
import org.videolan.resources.ACTION_RELOAD
import org.videolan.resources.ACTION_RESUME_SCAN
import org.videolan.resources.AndroidDevices
import org.videolan.resources.AppContextProvider
import org.videolan.resources.EXTRA_PARSE
import org.videolan.resources.EXTRA_PATH
import org.videolan.resources.EXTRA_REMOVE_DEVICE
import org.videolan.resources.EXTRA_UPGRADE
import org.videolan.resources.VLCInstance
import org.videolan.resources.util.dbExists
import org.videolan.resources.util.launchForeground
import org.videolan.resources.util.registerReceiverCompat
import org.videolan.resources.util.startForegroundCompat
import org.videolan.resources.util.stopForegroundCompat
import org.videolan.tools.*
import org.videolan.vlc.gui.SendCrashActivity
import org.videolan.tools.KEY_MEDIALIBRARY_AUTO_RESCAN
import org.videolan.tools.KEY_MEDIALIBRARY_SCAN
import org.videolan.tools.ML_SCAN_OFF
import org.videolan.tools.Settings
import org.videolan.tools.getContextWithLocale
import org.videolan.tools.localBroadcastManager
import org.videolan.tools.removeFileScheme
import org.videolan.vlc.gui.helpers.NotificationHelper
import org.videolan.vlc.repository.DirectoryRepository
import org.videolan.vlc.util.*
import org.videolan.vlc.util.FileUtils
import org.videolan.vlc.util.TextUtils
import org.videolan.vlc.util.Util
import org.videolan.vlc.util.cleanupWatchNextList
import org.videolan.vlc.util.scanAllowed
private const val TAG = "VLC/MediaParsingService"
@ -92,24 +125,6 @@ class MediaParsingService : LifecycleService(), DevicesDiscoveryCb {
var lastScheduled = -1
private val exceptionHandler = when {
BuildConfig.BETA -> Medialibrary.MedialibraryExceptionHandler { context, errMsg, _ ->
val intent = Intent(applicationContext, SendCrashActivity::class.java).apply {
putExtra(CRASH_ML_CTX, context)
putExtra(CRASH_ML_MSG, errMsg)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
Log.wtf(TAG, "medialibrary reported unhandled exception: -----------------")
// Lock the Medialibrary thread during DB extraction.
runBlocking {
SendCrashActivity.job = Job()
try {
startActivity(intent)
SendCrashActivity.job?.join()
} catch (e: Exception) {
SendCrashActivity.job = null
}
}
}
BuildConfig.DEBUG -> Medialibrary.MedialibraryExceptionHandler { context, errMsg, _ -> throw IllegalStateException("$context:\n$errMsg") }
else -> null
}

212
application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt

@ -1,212 +0,0 @@
/*
* *************************************************************************
* FilePickerActivity.java
* **************************************************************************
* Copyright © 2015 VLC authors and VideoLAN
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
* ***************************************************************************
*/
package org.videolan.vlc.gui
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.format.DateFormat
import android.text.format.Formatter
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.core.net.toUri
import androidx.core.text.HtmlCompat
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.*
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.interfaces.Medialibrary
import org.videolan.resources.AppContextProvider
import org.videolan.resources.CRASH_ML_CTX
import org.videolan.resources.CRASH_ML_MSG
import org.videolan.tools.AppUtils
import org.videolan.vlc.BuildConfig
import org.videolan.vlc.DebugLogService
import org.videolan.vlc.R
import org.videolan.vlc.databinding.SendCrashActivityBinding
import org.videolan.vlc.util.FileUtils
import org.videolan.vlc.util.Permissions
import java.io.File
import java.io.IOException
class SendCrashActivity : AppCompatActivity(), DebugLogService.Client.Callback {
private var logMessage = ""
override fun onStarted(logList: List<String>) {
logMessage = "Starting collecting logs at ${System.currentTimeMillis()}"
//initiate a log to wait for
Log.d("SendCrashActivity", logMessage)
}
override fun onStopped() {
}
override fun onLog(msg: String) {
//Wait for the log to initiate a save to avoid ANR
if (msg.contains(logMessage)) {
if (AndroidUtil.isOOrLater && !Permissions.canWriteStorage())
Permissions.askWriteStoragePermission(this, false) { client.save() }
else
client.save()
}
}
override fun onSaved(success: Boolean, path: String) {
if (!success) {
Snackbar.make(window.decorView, R.string.dump_logcat_failure, Snackbar.LENGTH_LONG).show()
client.stop()
return
}
lifecycleScope.launch(start = CoroutineStart.UNDISPATCHED) {
val emailIntent = withContext(Dispatchers.IO) {
client.stop()
if (!::logcatZipPath.isInitialized) {
val externalPath = AppContextProvider.appContext.getExternalFilesDir(null)?.absolutePath
?: return@withContext null
logcatZipPath = "$externalPath/logcat.zip"
}
val filesToAdd = mutableListOf(path)
//add previous crash logs
try {
AppContextProvider.appContext.getExternalFilesDir(null)?.absolutePath?.let { folder ->
File(folder).listFiles()?.forEach {
if (it.isFile && (it.name.contains("crash") || it.name.contains("logcat"))) filesToAdd.add(it.path)
}
}
} catch (exception: IOException) {
}
FileUtils.zip(filesToAdd.toTypedArray(), logcatZipPath)
try {
filesToAdd.forEach { FileUtils.deleteFile(it) }
} catch (exception: IOException) {
}
val emailIntent = Intent(Intent.ACTION_SEND_MULTIPLE)
emailIntent.type = "message/rfc822"
//get medialib db if needed
val attachments = ArrayList<Uri>()
if (binding.includeMedialibSwitch.isChecked) {
if (!::dbPath.isInitialized) {
val externalPath = AppContextProvider.appContext.getExternalFilesDir(null)?.absolutePath
?: return@withContext null
dbPath = "$externalPath/${Medialibrary.VLC_MEDIA_DB_NAME}"
dbZipPath = "$externalPath/db.zip"
}
val db = File(getDir("db", Context.MODE_PRIVATE).toString() + Medialibrary.VLC_MEDIA_DB_NAME)
val dbFile = File(dbPath)
FileUtils.copyFile(db, dbFile)
FileUtils.zip(arrayOf(dbPath), dbZipPath)
FileUtils.deleteFile(dbFile)
attachments.add(FileProvider.getUriForFile(this@SendCrashActivity, applicationContext.packageName + ".provider", File(dbZipPath)))
}
val appData = StringBuilder()
try {
appData.append("App version: ${BuildConfig.VLC_VERSION_NAME}<br/>App version code: ${BuildConfig.VLC_VERSION_CODE}<br/>")
} catch (e: PackageManager.NameNotFoundException) {
}
appData.append("Time: " + DateFormat.format("MM/dd/yyyy kk:mm:ss", System.currentTimeMillis()) + "<br/>")
appData.append("Device model: ${Build.MANUFACTURER} ${Build.MODEL}<br/>")
appData.append("Android version: ${Build.VERSION.SDK_INT}<br/>")
appData.append("System name: ${Build.DISPLAY}<br/>")
appData.append("Memory free: ${Formatter.formatFileSize(this@SendCrashActivity, AppUtils.freeMemory())} on ${Formatter.formatFileSize(this@SendCrashActivity, AppUtils.totalMemory())}")
attachments.add(FileProvider.getUriForFile(this@SendCrashActivity, applicationContext.packageName + ".provider", File(logcatZipPath)))
emailIntent.putExtra(Intent.EXTRA_STREAM, attachments)
emailIntent.type = "application/zip"
val describeCrash = if (::errMsg.isInitialized) {
"$errCtx:\n$errMsg"
} else {
getString(R.string.describe_crash)
}
val body = "<p>Here are my crash logs for VLC</strong></p><p style=3D\"color:#16171A;\"> [$describeCrash]</p><p>$appData</p>"
val htmlBody = HtmlCompat.fromHtml(body, HtmlCompat.FROM_HTML_MODE_LEGACY)
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf("vlc.crashreport+androidcrash@gmail.com"))
val subject = if (::errMsg.isInitialized) "[${BuildConfig.VLC_VERSION_NAME}] Medialibrary uncaught exception!"
else "[${BuildConfig.VLC_VERSION_NAME}] Crash logs for VLC"
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
emailIntent.putExtra(Intent.EXTRA_TEXT, htmlBody)
emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
emailIntent
}
emailIntent?.let { startActivity(it) }
finish()
}
}
private lateinit var client: DebugLogService.Client
private lateinit var binding: SendCrashActivityBinding
private lateinit var dbPath : String
private lateinit var dbZipPath : String
private lateinit var logcatZipPath : String
private lateinit var errMsg : String
private lateinit var errCtx : String
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.send_crash_activity)
binding.reportBugButton.setOnClickListener {
startActivity(Intent(Intent.ACTION_VIEW, "https://forum.videolan.org/viewforum.php?f=35".toUri()))
finish()
}
binding.reportCrashButton.setOnClickListener {
binding.crashFirstStepContainer.visibility = View.GONE
binding.crashSecondStepContainer.visibility = View.VISIBLE
client = DebugLogService.Client(this, this)
}
binding.sendCrashButton.setOnClickListener {
client.start()
binding.sendCrashButton.visibility = View.GONE
binding.sendCrashProgress.visibility = View.VISIBLE
}
errMsg = intent.extras?.getString(CRASH_ML_MSG) ?: return
errCtx = intent.extras?.getString(CRASH_ML_CTX) ?: return
binding.crashFirstStepContainer.visibility = View.GONE
binding.crashSecondStepContainer.visibility = View.VISIBLE
binding.includeMedialibSwitch.isChecked = true
client = DebugLogService.Client(this, this)
}
override fun onDestroy() {
job?.complete()
job = null
if (::client.isInitialized) client.release()
super.onDestroy()
}
companion object {
var job : CompletableJob? = null
}
}
Loading…
Cancel
Save