Skip to content

Commit e406142

Browse files
Merge pull request #16548 from nextcloud/exportLogs
Logs: allow to export
2 parents b0f4b75 + adfcd95 commit e406142

5 files changed

Lines changed: 101 additions & 10 deletions

File tree

app/src/main/java/com/nextcloud/client/logger/ui/LogsActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class LogsActivity : ToolbarActivity() {
8585
android.R.id.home -> finish()
8686
R.id.action_delete_logs -> vm.deleteAll()
8787
R.id.action_send_logs -> vm.send()
88+
R.id.action_export_logs -> vm.export()
8889
R.id.action_refresh_logs -> vm.load()
8990
else -> retval = super.onOptionsItemSelected(item)
9091
}

app/src/main/java/com/nextcloud/client/logger/ui/LogsEmailSender.kt

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,27 @@
66
*/
77
package com.nextcloud.client.logger.ui
88

9+
import android.app.DownloadManager
10+
import android.app.NotificationManager
11+
import android.app.PendingIntent
912
import android.content.ActivityNotFoundException
1013
import android.content.Context
1114
import android.content.Intent
15+
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
1216
import android.net.Uri
1317
import android.os.Build
1418
import android.widget.Toast
19+
import androidx.core.app.NotificationCompat
1520
import androidx.core.content.FileProvider
1621
import com.nextcloud.client.core.AsyncRunner
1722
import com.nextcloud.client.core.Cancellable
1823
import com.nextcloud.client.core.Clock
1924
import com.nextcloud.client.logger.LogEntry
2025
import com.owncloud.android.R
26+
import com.owncloud.android.ui.notifications.NotificationUtils
27+
import com.owncloud.android.utils.FileExportUtils
2128
import java.io.File
22-
import java.io.FileWriter
29+
import java.security.SecureRandom
2330
import java.util.TimeZone
2431

2532
class LogsEmailSender(private val context: Context, private val clock: Clock, private val runner: AsyncRunner) {
@@ -36,13 +43,17 @@ class LogsEmailSender(private val context: Context, private val clock: Clock, pr
3643
) : Function0<Uri?> {
3744

3845
override fun invoke(): Uri? {
39-
file.parentFile.mkdirs()
40-
val fo = FileWriter(file, false)
41-
logs.forEach {
42-
fo.write(it.toString(tz))
43-
fo.write("\n")
46+
file.parentFile?.mkdirs()
47+
48+
file.outputStream().use { outputStream ->
49+
outputStream.writer(Charsets.UTF_8).buffered().use { writer ->
50+
logs.forEach {
51+
writer.write(it.toString(tz))
52+
writer.newLine()
53+
}
54+
}
4455
}
45-
fo.close()
56+
4657
return FileProvider.getUriForFile(context, context.getString(R.string.file_provider_authority), file)
4758
}
4859
}
@@ -59,13 +70,78 @@ class LogsEmailSender(private val context: Context, private val clock: Clock, pr
5970
}
6071
}
6172

73+
fun export(logs: List<LogEntry>) {
74+
if (task == null) {
75+
val outFile = File(context.cacheDir, "attachments/logs.txt")
76+
task = runner.postQuickTask(Task(context, logs, outFile, clock.tz), onResult = {
77+
task = null
78+
export(outFile)
79+
})
80+
}
81+
}
82+
6283
fun stop() {
6384
if (task != null) {
6485
task?.cancel()
6586
task = null
6687
}
6788
}
6889

90+
private fun export(file: File) {
91+
FileExportUtils().exportFile(
92+
"Nextcloud Android Files Logs",
93+
"text/plain",
94+
context.contentResolver,
95+
null,
96+
file
97+
)
98+
showSuccessNotification(1)
99+
}
100+
101+
fun showSuccessNotification(successfulExports: Int) {
102+
showNotification(
103+
context.resources.getQuantityString(
104+
R.plurals.export_successful,
105+
successfulExports,
106+
successfulExports
107+
)
108+
)
109+
}
110+
111+
private fun showNotification(message: String) {
112+
val notificationId = SecureRandom().nextInt()
113+
114+
val notificationBuilder = NotificationCompat.Builder(
115+
context,
116+
NotificationUtils.NOTIFICATION_CHANNEL_DOWNLOAD
117+
)
118+
.setSmallIcon(R.drawable.notification_icon)
119+
.setContentTitle(message)
120+
.setAutoCancel(true)
121+
122+
val actionIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS).apply {
123+
flags = FLAG_ACTIVITY_NEW_TASK
124+
}
125+
val actionPendingIntent = PendingIntent.getActivity(
126+
context,
127+
notificationId,
128+
actionIntent,
129+
PendingIntent.FLAG_CANCEL_CURRENT or
130+
PendingIntent.FLAG_IMMUTABLE
131+
)
132+
notificationBuilder.addAction(
133+
NotificationCompat.Action(
134+
null,
135+
context.getString(R.string.locate_folder),
136+
actionPendingIntent
137+
)
138+
)
139+
140+
val notificationManager = context
141+
.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
142+
notificationManager.notify(notificationId, notificationBuilder.build())
143+
}
144+
69145
private fun send(uri: Uri?) {
70146
task = null
71147
val intent = Intent(Intent.ACTION_SEND_MULTIPLE)
@@ -76,12 +152,12 @@ class LogsEmailSender(private val context: Context, private val clock: Clock, pr
76152

77153
intent.putExtra(Intent.EXTRA_TEXT, getPhoneInfo())
78154

79-
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
155+
intent.flags = FLAG_ACTIVITY_NEW_TASK
80156
intent.type = LOGS_MIME_TYPE
81157
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, arrayListOf(uri))
82158
try {
83159
context.startActivity(intent)
84-
} catch (ex: ActivityNotFoundException) {
160+
} catch (_: ActivityNotFoundException) {
85161
Toast.makeText(context, R.string.log_send_no_mail_app, Toast.LENGTH_SHORT).show()
86162
}
87163
}

app/src/main/java/com/nextcloud/client/logger/ui/LogsViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ class LogsViewModel @Inject constructor(
4848
}
4949
}
5050

51+
fun export() {
52+
entries.value?.let {
53+
sender.export(it)
54+
}
55+
}
56+
5157
fun load() {
5258
if (isLoading.value != true) {
5359
logsRepository.load(this::onLoaded)

app/src/main/res/menu/activity_logs.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@
2525
android:title="@string/logs_menu_send"
2626
app:showAsAction="never"
2727
android:orderInCategory="200"
28-
android:icon="@drawable/ic_send"/>
28+
android:icon="@drawable/ic_send" />
29+
30+
<item
31+
android:id="@+id/action_export_logs"
32+
android:title="@string/logs_menu_export"
33+
app:showAsAction="never"
34+
android:orderInCategory="200"
35+
android:icon="@drawable/ic_export" />
2936

3037
<item
3138
android:id="@+id/action_delete_logs"

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@
659659
<string name="logs_title">Logs</string>
660660
<string name="logs_menu_refresh">Refresh</string>
661661
<string name="logs_menu_send">Send logs by email</string>
662+
<string name="logs_menu_export">Export logs</string>
662663
<string name="logs_menu_delete">Delete logs</string>
663664
<string name="log_send_no_mail_app">No app for sending logs found. Please install an email client.</string>
664665
<string name="log_send_mail_subject">%1$s Android app logs</string>

0 commit comments

Comments
 (0)