Skip to content
This repository was archived by the owner on Dec 18, 2022. It is now read-only.

Commit 7c23c65

Browse files
authored
Merge pull request #24 from 05nelsonm/mn/documentation/sample-code
Add sample code/Dokka docs
2 parents 672917f + 5a07a3c commit 7c23c65

File tree

19 files changed

+199
-21
lines changed

19 files changed

+199
-21
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ buildscript {
77
}
88
dependencies {
99
classpath deps.androidGradlePlugin
10+
classpath deps.dokka
1011
classpath deps.kotlin.gradlePlugin
1112
}
1213
}

gradle/dependencies.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ext.deps = [
2929
liveDataCore: "androidx.arch.core:core-testing:2.1.0",
3030
],
3131
],
32+
dokka: "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1",
3233
gradleVersions: "com.github.ben-manes:gradle-versions-plugin:0.20.0",
3334
jtorctl: "info.guardianproject:jtorctl:0.4",
3435
junit: "junit:junit:4.12",

sampleapp/src/main/java/io/matthewnelson/sampleapp/App.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ package io.matthewnelson.sampleapp
1919
import android.app.Application
2020
import io.matthewnelson.topl_service.TorServiceController
2121

22+
/**
23+
* @suppress
24+
* */
2225
class App: Application() {
2326

2427
companion object {

sampleapp/src/main/java/io/matthewnelson/sampleapp/LogMessageAdapter.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import androidx.lifecycle.Observer
2525
import androidx.recyclerview.widget.LinearLayoutManager
2626
import androidx.recyclerview.widget.RecyclerView
2727

28+
/**
29+
* @suppress
30+
* */
2831
class LogMessageAdapter(
2932
activity: MainActivity
3033
): RecyclerView.Adapter<LogMessageAdapter.LogMessageHolder>(){

sampleapp/src/main/java/io/matthewnelson/sampleapp/MainActivity.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import io.matthewnelson.topl_service.TorServiceController
2525
import io.matthewnelson.topl_service.util.ServiceConsts.PrefKeyBoolean
2626
import io.matthewnelson.topl_service.prefs.TorServicePrefs
2727

28+
/**
29+
* @suppress
30+
* */
2831
class MainActivity : AppCompatActivity() {
2932

3033
private companion object {

sampleapp/src/main/java/io/matthewnelson/sampleapp/MyEventBroadcaster.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import androidx.lifecycle.MutableLiveData
2121
import io.matthewnelson.topl_core_base.EventBroadcaster
2222
import io.matthewnelson.topl_service.util.ServiceUtilities
2323

24+
/**
25+
* @suppress
26+
* */
2427
class MyEventBroadcaster: EventBroadcaster() {
2528

2629

sampleapp/src/main/java/io/matthewnelson/sampleapp/MyTorSettings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import io.matthewnelson.topl_core_base.TorSettings
2020

2121
/**
2222
* See [TorSettings] for comments on what is what.
23+
* @suppress
2324
* */
2425
class MyTorSettings: TorSettings() {
2526

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package io.matthewnelson.sampleapp.samplecode
2+
3+
import android.app.Application
4+
import android.content.Context
5+
import androidx.core.app.NotificationCompat
6+
import io.matthewnelson.sampleapp.App
7+
import io.matthewnelson.sampleapp.BuildConfig
8+
import io.matthewnelson.sampleapp.MainActivity
9+
import io.matthewnelson.sampleapp.R
10+
import io.matthewnelson.topl_core_base.EventBroadcaster
11+
import io.matthewnelson.topl_core_base.TorConfigFiles
12+
import io.matthewnelson.topl_service.TorServiceController
13+
import java.io.File
14+
15+
/**
16+
* This class is for sample code that is to be used while creating Dokka Docs/MkDocs.
17+
* @suppress
18+
* */
19+
object SampleCode {
20+
21+
/**
22+
* Contains all possible options for initializing [TorServiceController.Builder]
23+
* */
24+
fun setupTorServices(
25+
application: Application,
26+
eventBroadcaster: EventBroadcaster,
27+
torConfigFiles: TorConfigFiles
28+
) {
29+
30+
TorServiceController.Builder(
31+
application = application,
32+
buildConfigVersionCode = BuildConfig.VERSION_CODE,
33+
torSettings = App.myTorSettings,
34+
35+
// These should live somewhere in your project application's assets directory
36+
geoipAssetPath = "common/geoip",
37+
geoip6AssetPath = "common/geoip6"
38+
)
39+
40+
.setBuildConfigDebug(BuildConfig.DEBUG)
41+
.setEventBroadcaster(eventBroadcaster)
42+
.useCustomTorConfigFiles(torConfigFiles)
43+
44+
// Notification customization
45+
.customizeNotification(
46+
channelName = "TorService Channel",
47+
channelDescription = "Tor Channel",
48+
channelID = "My Sample Application",
49+
notificationID = 615
50+
)
51+
.setActivityToBeOpenedOnTap(
52+
clazz = MainActivity::class.java,
53+
intentExtrasKey = null,
54+
intentExtras = null,
55+
intentRequestCode = null
56+
)
57+
.setImageTorNetworkingEnabled(R.drawable.tor_stat_network_enabled)
58+
.setImageTorNetworkingDisabled(R.drawable.tor_stat_network_disabled)
59+
.setImageTorDataTransfer(R.drawable.tor_stat_network_dataxfer)
60+
.setImageTorErrors(R.drawable.tor_stat_notifyerr)
61+
.setCustomColor(R.color.tor_service_white, colorizeBackground = true)
62+
.setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
63+
.enableTorRestartButton(enable = true)
64+
.enableTorStopButton(enable = true)
65+
66+
// Will return a Builder object to continue with non-notification related options
67+
.applyNotificationSettings()
68+
69+
.build()
70+
}
71+
72+
private fun customTorConfigFilesSetup(context: Context): TorConfigFiles {
73+
// This is modifying the directory hierarchy from TorService's
74+
// default setup. For example, if you are using binaries for Tor that
75+
// are named differently that that expressed in TorConfigFiles.createConfig()
76+
77+
// Post Android API 28 requires that executable files be contained in your
78+
// application's data/app directory, as they can no longer execute from data/data.
79+
val installDir = File(context.applicationInfo.nativeLibraryDir)
80+
81+
// Will create a directory within your application's data/data dir
82+
val configDir = context.getDir("torservice", Context.MODE_PRIVATE)
83+
84+
val builder = TorConfigFiles.Builder(installDir, configDir)
85+
86+
// Customize the tor executable file name. Requires that the executable file
87+
// be in your project's src/main/jniLibs directory. If you are getting your
88+
// executable files via a dependency, be sure to consult that Libraries documentation.
89+
builder.torExecutable(File(installDir, "libtor.so"))
90+
91+
// customize further via the builder methods...
92+
93+
return builder.build()
94+
}
95+
}

topl-core-base/build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
apply plugin: 'com.android.library'
22
apply plugin: 'kotlin-android'
33
apply plugin: 'kotlin-android-extensions'
4+
apply plugin: 'org.jetbrains.dokka'
45

56
android {
67
compileSdkVersion versions.compileSdk
@@ -34,6 +35,17 @@ android {
3435
}
3536
}
3637

38+
dokka {
39+
configuration {
40+
reportUndocumented = false
41+
includeNonPublic = false
42+
skipEmptyPackages = true
43+
samples = [
44+
"$rootDir/sampleapp/samplecode/SampleCode.kt".toString()
45+
]
46+
}
47+
}
48+
3749
dependencies {
3850
implementation fileTree(dir: "libs", include: ["*.jar"])
3951
implementation deps.kotlin.stdlib

topl-core-base/src/main/java/io/matthewnelson/topl_core_base/TorConfigFiles.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class TorConfigFiles private constructor(
181181
*
182182
* @param [installDir] directory where the tor binaries are installed.
183183
* @param [configDir] directory where the filesystem will be setup for tor.
184+
* @sample [io.matthewnelson.sampleapp.samplecode.SampleCode.customTorConfigFilesSetup]
184185
*/
185186
class Builder(private val installDir: File, private val configDir: File) {
186187

topl-core-base/src/main/java/io/matthewnelson/topl_core_base/TorSettings.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ package io.matthewnelson.topl_core_base
5757
*
5858
* Would **highly recommend** reading up on what's what:
5959
* - See <a href="https://2019.www.torproject.org/docs/tor-manual.html.en" target="_blank">docs</a>
60-
*
61-
* @sample [io.matthewnelson.sampleapp.MyTorSettings]
6260
* */
6361
abstract class TorSettings: BaseConsts() {
6462

topl-core/build.gradle

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
apply plugin: 'com.android.library'
22
apply plugin: 'kotlin-android'
33
apply plugin: 'kotlin-android-extensions'
4+
apply plugin: 'org.jetbrains.dokka'
45

56
android {
67
compileSdkVersion versions.compileSdk
@@ -34,6 +35,18 @@ android {
3435
}
3536
}
3637

38+
dokka {
39+
configuration {
40+
reportUndocumented = false
41+
includeNonPublic = false
42+
skipEmptyPackages = true
43+
samples = [
44+
"$rootDir/topl-service/service/TorService.kt".toString(),
45+
"$rootDir/topl-service/service/onionproxy/ServiceTorInstaller.kt".toString()
46+
]
47+
}
48+
}
49+
3750
dependencies {
3851
implementation fileTree(dir: "libs", include: ["*.jar"])
3952
implementation project(':topl-core-base')

topl-core/src/main/java/io/matthewnelson/topl_core/OnionProxyManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ import java.util.concurrent.TimeUnit
8686
* @param [buildConfigDebug] Send [BuildConfig.DEBUG] which will show Logcat messages for this
8787
* module on Debug builds of your Application. If `null`, all the messages will still be
8888
* broadcast to the provided [EventBroadcaster] and you can handle them there how you'd like.
89+
* @sample [io.matthewnelson.topl_service.service.TorService.initTOPLCore]
8990
* */
9091
class OnionProxyManager(
9192
private val context: Context,
@@ -853,7 +854,7 @@ class OnionProxyManager(
853854
eventListener.beginWatchingNoticeMsgs()
854855

855856
val signalSuccess = signalControlConnection(TorControlCommands.SIGNAL_NEWNYM)
856-
val rateLimited = eventListener.doesNoticeMsgBufferContain(NEWNYM_RATE_LIMIT_PARTIAL_MSG)
857+
val rateLimited = eventListener.doesNoticeMsgBufferContain(NEWNYM_RATE_LIMIT_PARTIAL_MSG, 50L)
857858

858859
if (signalSuccess) {
859860
if (!rateLimited) {

topl-core/src/main/java/io/matthewnelson/topl_core/listener/BaseEventListener.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ abstract class BaseEventListener: EventListener() {
4747
* See [TorControlCommands.EVENT_NAMES] values. These are **REQUIRED**
4848
* for registering them in [io.matthewnelson.topl_core.OnionProxyManager.start]
4949
* which allows you full control over what you wish to listen for.
50-
*
51-
* WARNING: Be careful as to what events your are attempting to listen for. If
52-
* jtorctl has not implemented that event yet it will crash.
53-
*
54-
* See <a href="https://github.com/05nelsonm/TorOnionProxyLibrary-Android/issues/14" target="_blank">this issue</a>
55-
* for more details.
5650
* */
5751
abstract val CONTROL_COMMAND_EVENTS: Array<String>
5852

@@ -72,17 +66,24 @@ abstract class BaseEventListener: EventListener() {
7266
delay(50)
7367
}
7468

75-
internal suspend fun doesNoticeMsgBufferContain(string: String): Boolean {
76-
delay(50)
69+
/**
70+
* Checks [noticeMsgBuffer] for the declared [string] and resets [noticeMsgBuffer] to null.
71+
*
72+
* @param [string] The string you wish to check for in [noticeMsgBuffer]
73+
* @param [delayMilliseconds] Length of time you wish to delay the coroutine for before executing
74+
* @return True if it contains the string, false if not.
75+
* */
76+
internal suspend fun doesNoticeMsgBufferContain(string: String, delayMilliseconds: Long): Boolean {
77+
delay(delayMilliseconds)
7778
val boolean = noticeMsgBuffer.toString().contains(string)
7879
noticeMsgBuffer = null
7980
return boolean
8081
}
8182

8283
/**
8384
* Requires that when you extend this class and override [noticeMsg], you **must**
84-
* use `super.noticeMsg(data)` within your override; otherwise, it will never get
85-
* messages to watch for the string value.
85+
* use `super.noticeMsg(data)` within your overridden method; otherwise, [noticeMsgBuffer]
86+
* [beginWatchingNoticeMsgs] and [doesNoticeMsgBufferContain] will not work correctly.
8687
* */
8788
override fun noticeMsg(data: String?) {
8889
noticeMsgBuffer?.append("${data}\n")

topl-core/src/main/java/io/matthewnelson/topl_core/settings/TorSettingsBuilder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import java.util.*
7474
*
7575
* @param [onionProxyContext] [OnionProxyContext]
7676
* @param [broadcastLogger] for broadcasting/logging
77+
* @sample [io.matthewnelson.topl_service.service.TorService.generateTorrcFile]
7778
* */
7879
class TorSettingsBuilder internal constructor(
7980
private val onionProxyContext: OnionProxyContext,

topl-core/src/main/java/io/matthewnelson/topl_core/util/TorInstaller.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ import java.io.IOException
4949
import java.io.InputStream
5050
import java.util.concurrent.TimeoutException
5151

52+
/**
53+
* Extend this class and implement the need methods.
54+
*
55+
* [setup] is called from [io.matthewnelson.topl_core.OnionProxyManager.setup] after
56+
* instantiation, and [openBridgesStream] is called from
57+
* [io.matthewnelson.topl_core.settings.TorSettingsBuilder.addBridgesFromResources]
58+
* when configuring bridge support.
59+
* */
5260
abstract class TorInstaller: CoreConsts() {
5361

5462
/**
@@ -67,6 +75,7 @@ abstract class TorInstaller: CoreConsts() {
6775
* the system this does not need to be invoked.
6876
*
6977
* @return true if tor installation is successful, otherwise false.
78+
* @sample [io.matthewnelson.topl_service.onionproxy.ServiceTorInstaller.setup]
7079
*/
7180
@Throws(IOException::class)
7281
abstract fun setup()
@@ -88,6 +97,8 @@ abstract class TorInstaller: CoreConsts() {
8897
* `($bridge_info \r\n)*`
8998
*
9099
* The second form is used for custom bridges from the user.
100+
*
101+
* @sample [io.matthewnelson.topl_service.onionproxy.ServiceTorInstaller.openBridgesStream]
91102
*/
92103
@Throws(IOException::class)
93104
abstract fun openBridgesStream(): InputStream?

topl-service/build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
apply plugin: 'com.android.library'
22
apply plugin: 'kotlin-android'
33
apply plugin: 'kotlin-android-extensions'
4+
apply plugin: 'org.jetbrains.dokka'
45

56
android {
67
compileSdkVersion versions.compileSdk
@@ -34,6 +35,17 @@ android {
3435
}
3536
}
3637

38+
dokka {
39+
configuration {
40+
reportUndocumented = false
41+
includeNonPublic = false
42+
skipEmptyPackages = true
43+
samples = [
44+
"$rootDir/sampleapp/samplecode/SampleCode.kt".toString()
45+
]
46+
}
47+
}
48+
3749
dependencies {
3850
implementation fileTree(dir: "libs", include: ["*.jar"])
3951
implementation project(':topl-core')

topl-service/src/main/java/io/matthewnelson/topl_service/TorServiceController.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class TorServiceController private constructor(): ServiceConsts() {
6565
* @param [geoip6AssetPath] The path to where you have your geoip6 file located (ex: in
6666
* assets/common directory, send this variable "common/geoip6").
6767
*
68-
* @sample [io.matthewnelson.sampleapp.App.setupTorServices]
68+
* @sample [io.matthewnelson.sampleapp.samplecode.SampleCode.setupTorServices]
6969
* */
7070
class Builder(
7171
private val application: Application,
@@ -122,9 +122,8 @@ class TorServiceController private constructor(): ServiceConsts() {
122122
* [Context.getApplicationContext] to set up a standard directory hierarchy for Tor
123123
* to operate with.
124124
*
125-
* See [Builder] for code samples.
126-
*
127125
* @return [Builder]
126+
* @sample [io.matthewnelson.sampleapp.samplecode.SampleCode.customTorConfigFilesSetup]
128127
* @see [Builder.build]
129128
* */
130129
fun useCustomTorConfigFiles(torConfigFiles: TorConfigFiles): Builder {
@@ -141,7 +140,8 @@ class TorServiceController private constructor(): ServiceConsts() {
141140
* @param [channelID] Your notification channel's ID (cannot be empty).
142141
* @param [channelDescription] Your notification channel's description (cannot be empty).
143142
* @param [notificationID] Your foreground notification's ID.
144-
* @return [NotificationBuilder] to obtain methods specific to notification customization.
143+
* @return [NotificationBuilder] To obtain methods specific to notification customization.
144+
* @throws [IllegalArgumentException] If String fields are empty.
145145
* */
146146
@Throws(IllegalArgumentException::class)
147147
fun customizeNotification(

0 commit comments

Comments
 (0)