1. added peer info cache

This commit is contained in:
Vadym 2020-12-06 16:51:20 +02:00
parent 8e0d575ed3
commit 296178c892
5 changed files with 101 additions and 24 deletions

1
.gitignore vendored
View File

@ -15,3 +15,4 @@
/yggdrasil/yggdrasil-sources.jar /yggdrasil/yggdrasil-sources.jar
/app/src/main/assets/yggdrasil-0.3.8-linux-arm64 /app/src/main/assets/yggdrasil-0.3.8-linux-arm64
/app/src/main/assets/yggdrasil-0.3.8-linux-armhf /app/src/main/assets/yggdrasil-0.3.8-linux-armhf
/.idea/

View File

@ -8,8 +8,8 @@ android {
applicationId "io.github.chronosx88.yggdrasil" applicationId "io.github.chronosx88.yggdrasil"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 30 targetSdkVersion 30
versionCode 5 versionCode 6
versionName "1.5" versionName "1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
setProperty("archivesBaseName", project.getParent().name+"-"+versionName) setProperty("archivesBaseName", project.getParent().name+"-"+versionName)
} }
@ -42,6 +42,10 @@ android {
// but continue the build even when errors are found: // but continue the build even when errors are found:
abortOnError false abortOnError false
} }
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
} }
task ndkBuild(type: Exec) { task ndkBuild(type: Exec) {
@ -59,16 +63,18 @@ dependencies {
implementation project(path: ':yggdrasil') implementation project(path: ':yggdrasil')
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.preference:preference-ktx:1.1.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation 'com.google.android.material:material:1.3.0-alpha02' implementation 'com.google.android.material:material:1.3.0-alpha04'
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.hbb20:ccp:2.4.0' implementation 'com.hbb20:ccp:2.4.0'
implementation 'com.vincentbrison.openlibraries.android:dualcache:3.1.1'
implementation 'com.vincentbrison.openlibraries.android:dualcache-jsonserializer:3.1.1'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
} }

View File

@ -15,9 +15,13 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.hbb20.CCPCountry import com.hbb20.CCPCountry
import com.vincentbrison.openlibraries.android.dualcache.Builder
import com.vincentbrison.openlibraries.android.dualcache.SizeOf
import com.vincentbrison.openlibraries.android.dualcache.JsonSerializer
import io.github.chronosx88.yggdrasil.models.PeerInfo import io.github.chronosx88.yggdrasil.models.PeerInfo
import io.github.chronosx88.yggdrasil.models.Status import io.github.chronosx88.yggdrasil.models.Status
import io.github.chronosx88.yggdrasil.models.config.DropDownAdapter import io.github.chronosx88.yggdrasil.models.config.DropDownAdapter
import io.github.chronosx88.yggdrasil.models.config.Peer
import io.github.chronosx88.yggdrasil.models.config.SelectPeerInfoListAdapter import io.github.chronosx88.yggdrasil.models.config.SelectPeerInfoListAdapter
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2PeerInfoSet import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.deserializeStringList2PeerInfoSet
import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.ping import io.github.chronosx88.yggdrasil.models.config.Utils.Companion.ping
@ -39,6 +43,12 @@ class PeerListActivity : AppCompatActivity() {
companion object { companion object {
const val PEER_LIST_URL = "https://publicpeers.neilalexander.dev/publicnodes.json" const val PEER_LIST_URL = "https://publicpeers.neilalexander.dev/publicnodes.json"
const val CACHE_NAME = "PEER_LIST_CACHE"
const val ONLINE_PEERINFO_LIST = "ONLINE_PEERINFO_LIST"
const val OFFLINE_PEERINFO_LIST = "OFFLINE_PEERINFO_LIST"
const val TEST_APP_VERSION = BuildConfig.VERSION_CODE;
const val RAM_MAX_SIZE = 100000
const val DISK_MAX_SIZE = 100000
} }
fun downloadJson(link: String): String { fun downloadJson(link: String): String {
@ -51,8 +61,6 @@ class PeerListActivity : AppCompatActivity() {
} }
} }
var isLoading = true;
var popup: PopupWindow? = null var popup: PopupWindow? = null
var adapter: DropDownAdapter? = null var adapter: DropDownAdapter? = null
@ -67,6 +75,13 @@ class PeerListActivity : AppCompatActivity() {
var peerList = findViewById<ListView>(R.id.peerList) var peerList = findViewById<ListView>(R.id.peerList)
var adapter = SelectPeerInfoListAdapter(this, arrayListOf(), mutableSetOf()) var adapter = SelectPeerInfoListAdapter(this, arrayListOf(), mutableSetOf())
peerList.adapter = adapter peerList.adapter = adapter
var peerInfoListCache = Builder<List<PeerInfo>>(CACHE_NAME, TEST_APP_VERSION)
.enableLog()
.useReferenceInRam(RAM_MAX_SIZE, SizeOfPeerList())
.useSerializerInDisk(
DISK_MAX_SIZE, true,
JsonSerializer(ArrayList<PeerInfo>().javaClass), baseContext
).build();
GlobalScope.launch { GlobalScope.launch {
try { try {
@ -94,7 +109,12 @@ class PeerListActivity : AppCompatActivity() {
try { try {
var address = InetAddress.getByName(url.host) var address = InetAddress.getByName(url.host)
var peerInfo = var peerInfo =
PeerInfo(url.scheme, address, url.port, ccp.nameCode) PeerInfo(
url.scheme,
address,
url.port,
ccp.nameCode
)
var ping = ping(address, url.port) var ping = ping(address, url.port)
peerInfo.ping = ping peerInfo.ping = ping
if(cp.contains(peerInfo)){ if(cp.contains(peerInfo)){
@ -114,14 +134,38 @@ class PeerListActivity : AppCompatActivity() {
} }
} }
} }
} catch(e: FileNotFoundException){ var allPeersList = adapter.getAllPeers()
var cachePeerInfoList = mutableListOf<PeerInfo>()
for(p in allPeersList){
if(p.ping<Int.MAX_VALUE){
cachePeerInfoList.add(p)
}
}
if(cachePeerInfoList.size>0){
peerInfoListCache.put(ONLINE_PEERINFO_LIST, cachePeerInfoList.toList())
}
} catch (e: FileNotFoundException){
e.printStackTrace() e.printStackTrace()
var onlinePeerInfoList = peerInfoListCache.get(ONLINE_PEERINFO_LIST)
if(onlinePeerInfoList!=null) {
for (peerInfo in onlinePeerInfoList) {
var ping = ping(peerInfo.address, peerInfo.port)
peerInfo.ping = ping
if (cp.contains(peerInfo)) {
continue
}
withContext(Dispatchers.Main) {
adapter.addItem(peerInfo)
if (adapter.count % 5 == 0) {
adapter.sort()
}
}
}
}
} }
var currentPeers = ArrayList(cp.sortedWith(compareBy { it.ping })) var currentPeers = ArrayList(cp.sortedWith(compareBy { it.ping }))
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
adapter.addAll(0, currentPeers) adapter.addAll(0, currentPeers)
isLoading = false
adapter.setLoading(isLoading)
} }
} catch (e: Throwable){ } catch (e: Throwable){
e.printStackTrace() e.printStackTrace()
@ -150,7 +194,11 @@ class PeerListActivity : AppCompatActivity() {
schemaInput.setOnClickListener { v-> schemaInput.setOnClickListener { v->
onClickSchemaList(v) onClickSchemaList(v)
} }
getPopupWindow(R.layout.spinner_item, resources.getStringArray(R.array.schemas), schemaInput); getPopupWindow(
R.layout.spinner_item,
resources.getStringArray(R.array.schemas),
schemaInput
);
view.findViewById<com.hbb20.CountryCodePicker>(R.id.ccp).setCountryForNameCode(countryCode) view.findViewById<com.hbb20.CountryCodePicker>(R.id.ccp).setCountryForNameCode(countryCode)
val ab: AlertDialog.Builder = AlertDialog.Builder(this) val ab: AlertDialog.Builder = AlertDialog.Builder(this)
ab.setCancelable(true).setView(view) ab.setCancelable(true).setView(view)
@ -180,7 +228,7 @@ class PeerListActivity : AppCompatActivity() {
try { try {
var ping = ping(pi.address, pi.port) var ping = ping(pi.address, pi.port)
pi.ping = ping pi.ping = ping
} catch(e: Throwable){ } catch (e: Throwable){
pi.ping = Int.MAX_VALUE pi.ping = Int.MAX_VALUE
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -235,9 +283,6 @@ class PeerListActivity : AppCompatActivity() {
val saveButton = item val saveButton = item
.actionView.findViewById<Button>(R.id.saveButton) .actionView.findViewById<Button>(R.id.saveButton)
saveButton.setOnClickListener { saveButton.setOnClickListener {
if(isLoading){
return@setOnClickListener
}
val result = Intent(this, MainActivity::class.java) val result = Intent(this, MainActivity::class.java)
var adapter = findViewById<ListView>(R.id.peerList).adapter as SelectPeerInfoListAdapter var adapter = findViewById<ListView>(R.id.peerList).adapter as SelectPeerInfoListAdapter
val selectedPeers = adapter.getSelectedPeers() val selectedPeers = adapter.getSelectedPeers()
@ -248,3 +293,29 @@ class PeerListActivity : AppCompatActivity() {
return true return true
} }
} }
class SizeOfPeerList: SizeOf<List<PeerInfo>> {
override fun sizeOf(obj: List<PeerInfo>): Int{
var size = 0
for (o in obj) {
if (o.address != null) {
size += o.address.toString().length * 2
}
if (o.hostName != null) {
size += o.hostName.length * 2
}
if (o.schema != null) {
size += o.schema.length * 2
}
if (o.countryCode != null) {
size += o.countryCode!!.length * 2
}
size += 4
size += 4
size += 1
}
return size
}
}

View File

@ -18,7 +18,6 @@ class SelectPeerInfoListAdapter(
currentPeers: MutableSet<PeerInfo> currentPeers: MutableSet<PeerInfo>
) : ArrayAdapter<PeerInfo?> (context, 0, allPeers) { ) : ArrayAdapter<PeerInfo?> (context, 0, allPeers) {
private var isLoading = true
private val mContext: Context = context private val mContext: Context = context
private var allPeers: MutableList<PeerInfo> = allPeers as MutableList<PeerInfo> private var allPeers: MutableList<PeerInfo> = allPeers as MutableList<PeerInfo>
private var currentPeers: MutableSet<PeerInfo> = currentPeers private var currentPeers: MutableSet<PeerInfo> = currentPeers
@ -75,6 +74,10 @@ class SelectPeerInfoListAdapter(
return currentPeers return currentPeers
} }
fun getAllPeers(): List<PeerInfo> {
return allPeers
}
fun addItem(peerInfo: PeerInfo){ fun addItem(peerInfo: PeerInfo){
allPeers.add(peerInfo) allPeers.add(peerInfo)
} }
@ -95,10 +98,6 @@ class SelectPeerInfoListAdapter(
this.notifyDataSetChanged() this.notifyDataSetChanged()
} }
fun setLoading(loading: Boolean){
this.isLoading = loading
}
class PeerInfoHolder { class PeerInfoHolder {
lateinit var checkbox: CheckBox lateinit var checkbox: CheckBox
lateinit var countryFlag: ImageView lateinit var countryFlag: ImageView

View File

@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.72' ext.kotlin_version = '1.4.10'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files