diff options
12 files changed, 177 insertions, 9 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6826920..8fc83b3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml | |||
@@ -48,6 +48,12 @@ | |||
48 | </intent-filter> | 48 | </intent-filter> |
49 | </activity> | 49 | </activity> |
50 | 50 | ||
51 | <activity | ||
52 | android:name=".activities.ViewLogActivity" | ||
53 | android:configChanges="orientation|screenSize" | ||
54 | android:theme="@style/AppTheme.NoActionBar"> | ||
55 | </activity> | ||
56 | |||
51 | <service | 57 | <service |
52 | android:name="org.pacien.tincapp.service.TincVpnService" | 58 | android:name="org.pacien.tincapp.service.TincVpnService" |
53 | android:permission="android.permission.BIND_VPN_SERVICE"> | 59 | android:permission="android.permission.BIND_VPN_SERVICE"> |
diff --git a/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt b/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt index 1872081..351305c 100644 --- a/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt +++ b/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt | |||
@@ -123,6 +123,9 @@ class StatusActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRef | |||
123 | TincVpnService.disconnect() | 123 | TincVpnService.disconnect() |
124 | } | 124 | } |
125 | 125 | ||
126 | fun openLogViewer(@Suppress("UNUSED_PARAMETER") i: MenuItem) = | ||
127 | startActivity(Intent(this, ViewLogActivity::class.java)) | ||
128 | |||
126 | private fun writeNetworkInfo(cfg: VpnInterfaceConfiguration) { | 129 | private fun writeNetworkInfo(cfg: VpnInterfaceConfiguration) { |
127 | text_network_name.text = TincVpnService.getCurrentNetName() ?: getString(R.string.value_none) | 130 | text_network_name.text = TincVpnService.getCurrentNetName() ?: getString(R.string.value_none) |
128 | text_network_ip_addresses.setText(cfg.addresses.map { it.toSlashSeparated() }) | 131 | text_network_ip_addresses.setText(cfg.addresses.map { it.toSlashSeparated() }) |
diff --git a/app/src/main/java/org/pacien/tincapp/activities/ViewLogActivity.kt b/app/src/main/java/org/pacien/tincapp/activities/ViewLogActivity.kt new file mode 100644 index 0000000..67df51b --- /dev/null +++ b/app/src/main/java/org/pacien/tincapp/activities/ViewLogActivity.kt | |||
@@ -0,0 +1,90 @@ | |||
1 | package org.pacien.tincapp.activities | ||
2 | |||
3 | import android.os.Bundle | ||
4 | import android.text.method.ScrollingMovementMethod | ||
5 | import android.view.Menu | ||
6 | import android.view.MenuItem | ||
7 | import kotlinx.android.synthetic.main.base.* | ||
8 | import kotlinx.android.synthetic.main.page_viewlog.* | ||
9 | import org.pacien.tincapp.R | ||
10 | import org.pacien.tincapp.commands.Executor | ||
11 | import org.pacien.tincapp.commands.Tinc | ||
12 | import org.pacien.tincapp.service.TincVpnService | ||
13 | |||
14 | /** | ||
15 | * @author pacien | ||
16 | */ | ||
17 | class ViewLogActivity : BaseActivity() { | ||
18 | companion object { | ||
19 | private const val LOG_LEVEL = 4 | ||
20 | private const val NEW_LINE = "\n" | ||
21 | } | ||
22 | |||
23 | private var logger: Process? = null | ||
24 | |||
25 | override fun onCreate(savedInstanceState: Bundle?) { | ||
26 | super.onCreate(savedInstanceState) | ||
27 | supportActionBar!!.setDisplayHomeAsUpEnabled(true) | ||
28 | layoutInflater.inflate(R.layout.page_viewlog, main_content) | ||
29 | startLogging() | ||
30 | } | ||
31 | |||
32 | override fun onCreateOptionsMenu(m: Menu): Boolean { | ||
33 | menuInflater.inflate(R.menu.menu_viewlog, m) | ||
34 | return super.onCreateOptionsMenu(m) | ||
35 | } | ||
36 | |||
37 | override fun onSupportNavigateUp(): Boolean { | ||
38 | finish() | ||
39 | return true | ||
40 | } | ||
41 | |||
42 | override fun onDestroy() { | ||
43 | stopLogging() | ||
44 | super.onDestroy() | ||
45 | } | ||
46 | |||
47 | fun toggleLogging(menuItem: MenuItem) { | ||
48 | if (logger == null) { | ||
49 | startLogging() | ||
50 | text_log.movementMethod = null | ||
51 | text_log.setTextIsSelectable(false) | ||
52 | menuItem.setIcon(R.drawable.ic_pause_circle_outline_primary_24dp) | ||
53 | } else { | ||
54 | stopLogging() | ||
55 | text_log.movementMethod = ScrollingMovementMethod.getInstance() | ||
56 | text_log.setTextIsSelectable(true) | ||
57 | menuItem.setIcon(R.drawable.ic_pause_circle_filled_primary_24dp) | ||
58 | } | ||
59 | } | ||
60 | |||
61 | private fun startLogging(level: Int = LOG_LEVEL) { | ||
62 | text_log.append(NEW_LINE) | ||
63 | text_log.append(resources.getString(R.string.message_log_level_set, level)) | ||
64 | text_log.append(NEW_LINE) | ||
65 | |||
66 | Tinc.log(TincVpnService.getCurrentNetName()!!, level).let { process -> | ||
67 | logger = process | ||
68 | Executor.runAsyncTask { printLog(process) } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | private fun stopLogging() { | ||
73 | logger?.destroy() | ||
74 | logger = null | ||
75 | } | ||
76 | |||
77 | private fun printLog(logger: Process) { | ||
78 | logger.inputStream?.use { inputStream -> | ||
79 | inputStream.bufferedReader().useLines { lines -> | ||
80 | lines.forEach { | ||
81 | text_log.post { | ||
82 | text_log.append(NEW_LINE) | ||
83 | text_log.append(it) | ||
84 | text_log.append(NEW_LINE) | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
diff --git a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt index 39c413e..96e48b9 100644 --- a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt +++ b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt | |||
@@ -47,16 +47,16 @@ internal object Executor { | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | fun call(cmd: Command): CompletableFuture<List<String>> { | 50 | fun run(cmd: Command): Process = try { |
51 | val proc = try { | 51 | ProcessBuilder(cmd.asList()).start() |
52 | ProcessBuilder(cmd.asList()).start() | 52 | } catch (e: IOException) { |
53 | } catch (e: IOException) { | 53 | throw CommandExecutionException(e.message ?: "Could not start process.") |
54 | throw CommandExecutionException(e.message ?: "Could not start process.") | 54 | } |
55 | } | ||
56 | 55 | ||
57 | return supplyAsyncTask<List<String>> { | 56 | fun call(cmd: Command): CompletableFuture<List<String>> = run(cmd).let { process -> |
58 | if (proc.waitFor() == 0) read(proc.inputStream) | 57 | supplyAsyncTask<List<String>> { |
59 | else throw CommandExecutionException(read(proc.errorStream).lastOrNull() ?: "Non-zero exit status.") | 58 | if (process.waitFor() == 0) read(process.inputStream) |
59 | else throw CommandExecutionException(read(process.errorStream).lastOrNull() ?: "Non-zero exit status.") | ||
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
diff --git a/app/src/main/java/org/pacien/tincapp/commands/Tinc.kt b/app/src/main/java/org/pacien/tincapp/commands/Tinc.kt index 556288a..0f4c0a4 100644 --- a/app/src/main/java/org/pacien/tincapp/commands/Tinc.kt +++ b/app/src/main/java/org/pacien/tincapp/commands/Tinc.kt | |||
@@ -46,4 +46,9 @@ object Tinc { | |||
46 | .withOption("config", AppPaths.confDir(netName).absolutePath) | 46 | .withOption("config", AppPaths.confDir(netName).absolutePath) |
47 | .withArguments("join", invitationUrl)) | 47 | .withArguments("join", invitationUrl)) |
48 | .thenApply<String> { it.joinToString("\n") } | 48 | .thenApply<String> { it.joinToString("\n") } |
49 | |||
50 | fun log(netName: String, level: Int? = null): Process = | ||
51 | Executor.run(newCommand(netName) | ||
52 | .withArguments("log") | ||
53 | .apply { if (level != null) withArguments(level.toString()) }) | ||
49 | } | 54 | } |
diff --git a/app/src/main/res/drawable/ic_pause_circle_filled_primary_24dp.xml b/app/src/main/res/drawable/ic_pause_circle_filled_primary_24dp.xml new file mode 100644 index 0000000..84ac134 --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_circle_filled_primary_24dp.xml | |||
@@ -0,0 +1,9 @@ | |||
1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
2 | android:width="24dp" | ||
3 | android:height="24dp" | ||
4 | android:viewportHeight="24.0" | ||
5 | android:viewportWidth="24.0"> | ||
6 | <path | ||
7 | android:fillColor="@color/textPrimary" | ||
8 | android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,16L9,16L9,8h2v8zM15,16h-2L13,8h2v8z"/> | ||
9 | </vector> | ||
diff --git a/app/src/main/res/drawable/ic_pause_circle_outline_primary_24dp.xml b/app/src/main/res/drawable/ic_pause_circle_outline_primary_24dp.xml new file mode 100644 index 0000000..9374a21 --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_circle_outline_primary_24dp.xml | |||
@@ -0,0 +1,9 @@ | |||
1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
2 | android:width="24dp" | ||
3 | android:height="24dp" | ||
4 | android:viewportHeight="24.0" | ||
5 | android:viewportWidth="24.0"> | ||
6 | <path | ||
7 | android:fillColor="@color/textPrimary" | ||
8 | android:pathData="M9,16h2L11,8L9,8v8zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM13,16h2L15,8h-2v8z"/> | ||
9 | </vector> | ||
diff --git a/app/src/main/res/drawable/ic_receipt_primary_24dp.xml b/app/src/main/res/drawable/ic_receipt_primary_24dp.xml new file mode 100644 index 0000000..4ce8a76 --- /dev/null +++ b/app/src/main/res/drawable/ic_receipt_primary_24dp.xml | |||
@@ -0,0 +1,9 @@ | |||
1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||