mirror of
https://github.com/yggdrasil-network/crispa-android.git
synced 2024-11-09 20:11:01 +00:00
1. implemented peers list load from json, iteration #2
https://publicpeers.neilalexander.dev/publicnodes.json
This commit is contained in:
parent
4f53e50e3e
commit
28eb0903ef
@ -39,31 +39,21 @@ android {
|
||||
}
|
||||
|
||||
|
||||
task ndkBuild(type: Exec) {
|
||||
def rootDir = project.rootDir
|
||||
workingDir = new File(rootDir,"yggdrasil")
|
||||
commandLine 'make'
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
tasks.compileDebugKotlin.dependsOn(ndkBuild)
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(path: ':yggdrasil')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha01'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'com.hbb20:ccp:2.4.0'
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
@ -12,6 +12,11 @@ import android.view.View
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.gson.Gson
|
||||
import io.github.chronosx88.yggdrasil.models.PeerInfo
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
@ -122,10 +127,11 @@ class MainActivity : AppCompatActivity() {
|
||||
val i = baseContext.packageManager
|
||||
.getLaunchIntentForPackage(baseContext.packageName)
|
||||
i!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
i!!.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
i.putExtra(START_VPN, true)
|
||||
startActivity(i)
|
||||
finish()
|
||||
startActivity(i)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,7 +167,7 @@ class MainActivity : AppCompatActivity() {
|
||||
} else {
|
||||
switchOn.isChecked = false
|
||||
}
|
||||
switchOn.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
switchOn.setOnCheckedChangeListener { _, isChecked ->
|
||||
if (isChecked) {
|
||||
startVpn()
|
||||
} else {
|
||||
@ -171,4 +177,22 @@ class MainActivity : AppCompatActivity() {
|
||||
return true
|
||||
}
|
||||
|
||||
fun deserializeStringList2PeerInfoList(list: ArrayList<String>): ArrayList<PeerInfo> {
|
||||
var gson = Gson()
|
||||
var out = ArrayList<PeerInfo>()
|
||||
for(s in list) {
|
||||
out.add(gson.fromJson(s, PeerInfo::class.java))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
fun serializePeerInfoList2StringSet(list: ArrayList<PeerInfo>): Set<String> {
|
||||
var gson = Gson()
|
||||
var out = TreeSet<String>()
|
||||
for(p in list) {
|
||||
out.add(gson.toJson(p))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,96 +12,154 @@ import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.hbb20.CountryCodePicker
|
||||
import io.github.chronosx88.yggdrasil.models.config.PeerInfo
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.hbb20.CCPCountry
|
||||
import io.github.chronosx88.yggdrasil.models.PeerInfo
|
||||
import io.github.chronosx88.yggdrasil.models.Status
|
||||
import io.github.chronosx88.yggdrasil.models.config.PeerInfoListAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.lang.reflect.Type
|
||||
import java.net.Inet4Address
|
||||
import java.net.InetAddress
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
import java.nio.charset.Charset
|
||||
|
||||
|
||||
class PeerListActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
val peers = arrayListOf(
|
||||
const val PEER_LIST_URL = "https://publicpeers.neilalexander.dev/publicnodes.json"
|
||||
|
||||
var allPeers = arrayListOf(
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("194.177.21.156"),
|
||||
5066,
|
||||
"RU",
|
||||
CountryCodePicker.Language.RUSSIAN
|
||||
"RU"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("46.151.26.194"),
|
||||
60575,
|
||||
"RU",
|
||||
CountryCodePicker.Language.RUSSIAN
|
||||
"RU"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("188.226.125.64"),
|
||||
54321,
|
||||
"RU",
|
||||
CountryCodePicker.Language.RUSSIAN
|
||||
"RU"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("88.201.129.205"),
|
||||
8777,
|
||||
"RU",
|
||||
CountryCodePicker.Language.RUSSIAN
|
||||
"RU"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("45.11.19.26"),
|
||||
5001,
|
||||
"DE",
|
||||
CountryCodePicker.Language.GERMAN
|
||||
"DE"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("82.165.69.111"),
|
||||
61216,
|
||||
"DE",
|
||||
CountryCodePicker.Language.GERMAN
|
||||
"DE"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("104.248.15.125"),
|
||||
31337,
|
||||
"US",
|
||||
CountryCodePicker.Language.ENGLISH
|
||||
"US"
|
||||
),
|
||||
PeerInfo(
|
||||
"tcp",
|
||||
Inet4Address.getByName("108.175.10.127"),
|
||||
61216,
|
||||
"US",
|
||||
CountryCodePicker.Language.ENGLISH
|
||||
"US"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun downloadJson(link: String): String {
|
||||
URL(link).openStream().use { input ->
|
||||
var outStream = ByteArrayOutputStream()
|
||||
outStream.use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
return String(outStream.toByteArray(), Charset.forName("UTF-8"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_peer_list)
|
||||
setSupportActionBar(findViewById(R.id.toolbar))
|
||||
|
||||
findViewById<FloatingActionButton>(R.id.fab).setOnClickListener { view ->
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show()
|
||||
}
|
||||
var extras = intent.getExtras()
|
||||
var extras = intent.extras
|
||||
var peerList = findViewById<ListView>(R.id.peerList)
|
||||
var instance = this
|
||||
GlobalScope.launch {
|
||||
var json = downloadJson(PEER_LIST_URL)
|
||||
var countries = CCPCountry.getLibraryMasterCountriesEnglish()
|
||||
val mapType: Type = object :
|
||||
TypeToken<Map<String?, Map<String, Status>>>() {}.type
|
||||
val peersMap: Map<String, Map<String, Status>> = Gson().fromJson(json, mapType)
|
||||
val allOnlinePeers = arrayListOf<PeerInfo>()
|
||||
for ((country, peers) in peersMap.entries) {
|
||||
println("$country:")
|
||||
for ((peer, status) in peers) {
|
||||
if(status.up){
|
||||
for (ccp in countries){
|
||||
if(ccp.name.toLowerCase().contains(country.replace(".md",""))){
|
||||
var url = URI(peer)
|
||||
var peerInfo = PeerInfo(url.scheme, InetAddress.getByName(url.host), url.port, ccp.nameCode)
|
||||
allOnlinePeers.add(peerInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(allOnlinePeers.size>0){
|
||||
allPeers = allOnlinePeers
|
||||
}
|
||||
|
||||
if (extras != null) {
|
||||
var currentPeers = extras.getStringArrayList(MainActivity.PEER_LIST)!!
|
||||
var adapter = PeerInfoListAdapter(this, peers, currentPeers)
|
||||
var cp = extras.getStringArrayList(MainActivity.PEER_LIST)!!
|
||||
var currentPeers = ArrayList(cp)
|
||||
for(peerInfo in allPeers){
|
||||
if(currentPeers.contains(peerInfo.toString())){
|
||||
currentPeers.remove(peerInfo.toString())
|
||||
}
|
||||
}
|
||||
for(cp in currentPeers){
|
||||
var url = URI(cp)
|
||||
var peerInfo = PeerInfo(url.scheme, InetAddress.getByName(url.host), url.port, "RU")
|
||||
allPeers.add(0, peerInfo)
|
||||
}
|
||||
var adapter = PeerInfoListAdapter(instance, allOnlinePeers, cp)
|
||||
withContext(Dispatchers.Main) {
|
||||
peerList.adapter = adapter
|
||||
}
|
||||
} else {
|
||||
var adapter = PeerInfoListAdapter(this, peers, ArrayList())
|
||||
var adapter = PeerInfoListAdapter(instance, allOnlinePeers, ArrayList())
|
||||
withContext(Dispatchers.Main) {
|
||||
peerList.adapter = adapter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
|
@ -146,8 +146,8 @@ class YggdrasilTunService : VpnService() {
|
||||
|
||||
private fun stopVpn(pi: PendingIntent) {
|
||||
isClosed = true;
|
||||
readCoroutine!!.cancel()
|
||||
writeCoroutine!!.cancel()
|
||||
readCoroutine.cancel()
|
||||
writeCoroutine.cancel()
|
||||
tunInputStream!!.close()
|
||||
tunOutputStream!!.close()
|
||||
tunInterface!!.close()
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.chronosx88.yggdrasil.models.config
|
||||
package io.github.chronosx88.yggdrasil.models
|
||||
|
||||
import android.content.Context
|
||||
import com.hbb20.CCPCountry
|
||||
@ -7,26 +7,37 @@ import java.net.InetAddress
|
||||
|
||||
|
||||
class PeerInfo {
|
||||
constructor(schema: String, address: InetAddress, port: Int, countryCode: String, language: CountryCodePicker.Language){
|
||||
constructor(schema: String, address: InetAddress, port: Int, countryCode: String){
|
||||
this.schema = schema
|
||||
this.address = address
|
||||
this.port = port
|
||||
this.countryCode = countryCode
|
||||
this.language = language
|
||||
}
|
||||
var schema: String
|
||||
var address: InetAddress
|
||||
var port = 0
|
||||
var countryCode: String
|
||||
var language: CountryCodePicker.Language
|
||||
var ping: Float = Float.MAX_VALUE
|
||||
|
||||
override fun toString(): String {
|
||||
return this.schema+":/"+address.toString()+":"+port
|
||||
var a = address.toString();
|
||||
if(a.indexOf("/")>0){
|
||||
return this.schema+"://"+a.split("/")[0]+":"+port
|
||||
} else {
|
||||
if(a.contains(":")) {
|
||||
return this.schema + "://[" + a.substring(1) + "]:" + port
|
||||
} else {
|
||||
return this.schema + ":/" + a + ":" + port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return toString() == other.toString()
|
||||
}
|
||||
|
||||
fun getCountry(context: Context): CCPCountry? {
|
||||
return CCPCountry.getCountryForNameCodeFromLibraryMasterList(context, language, countryCode)
|
||||
return CCPCountry.getCountryForNameCodeFromLibraryMasterList(context, CountryCodePicker.Language.ENGLISH, countryCode)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package io.github.chronosx88.yggdrasil.models
|
||||
|
||||
class Status {
|
||||
var up: Boolean = false
|
||||
}
|
@ -9,6 +9,7 @@ import android.widget.CheckBox
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import io.github.chronosx88.yggdrasil.R
|
||||
import io.github.chronosx88.yggdrasil.models.PeerInfo
|
||||
import java.util.ArrayList
|
||||
|
||||
|
||||
@ -23,19 +24,22 @@ class PeerInfoListAdapter(
|
||||
private var currentPeers: ArrayList<String> = currentPeers
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
|
||||
var peerInfoHolder = PeerInfoHolder()
|
||||
var listItem: View? = convertView
|
||||
if (listItem == null) {
|
||||
listItem = LayoutInflater.from(mContext).inflate(R.layout.peers_list_item_edit, parent, false)
|
||||
peerInfoHolder.checkbox = listItem.findViewById(R.id.checkbox) as CheckBox
|
||||
peerInfoHolder.countryFlag = listItem.findViewById(R.id.countryFlag) as ImageView
|
||||
peerInfoHolder.peerInfoText = listItem.findViewById(R.id.peerInfoText) as TextView
|
||||
listItem.tag = peerInfoHolder
|
||||
} else {
|
||||
peerInfoHolder = listItem.tag as PeerInfoHolder
|
||||
}
|
||||
val currentPeer = allPeers[position]
|
||||
val image: ImageView = listItem?.findViewById(R.id.countryFlag) as ImageView
|
||||
image.setImageResource(currentPeer.getCountry(mContext)!!.flagID)
|
||||
val name = listItem.findViewById(R.id.peerInfoText) as TextView
|
||||
peerInfoHolder.countryFlag.setImageResource(currentPeer.getCountry(mContext)!!.flagID)
|
||||
val peerId = currentPeer.toString()
|
||||
name.text = peerId
|
||||
val checkbox = listItem.findViewById(R.id.checkbox) as CheckBox
|
||||
checkbox.setOnCheckedChangeListener { buttonView, isChecked ->
|
||||
peerInfoHolder.peerInfoText.text = peerId
|
||||
peerInfoHolder.checkbox.setOnCheckedChangeListener { _, isChecked ->
|
||||
if(isChecked){
|
||||
if(!currentPeers.contains(peerId)){
|
||||
currentPeers.add(peerId)
|
||||
@ -46,14 +50,21 @@ class PeerInfoListAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
peerInfoHolder.checkbox.isChecked = this.currentPeers.contains(peerId)
|
||||
if(this.currentPeers.contains(peerId)){
|
||||
checkbox.isChecked = true
|
||||
print(peerId)
|
||||
}
|
||||
return listItem
|
||||
return listItem!!
|
||||
}
|
||||
|
||||
public fun getSelectedPeers(): ArrayList<String> {
|
||||
fun getSelectedPeers(): ArrayList<String> {
|
||||
return currentPeers
|
||||
}
|
||||
|
||||
class PeerInfoHolder {
|
||||
lateinit var checkbox: CheckBox
|
||||
lateinit var countryFlag: ImageView
|
||||
lateinit var peerInfoText: TextView
|
||||
}
|
||||
|
||||
}
|
16
app/src/main/res/drawable/checkbox_rounded_corner.xml
Normal file
16
app/src/main/res/drawable/checkbox_rounded_corner.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@android:color/transparent" />
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
<padding
|
||||
android:left="1dp"
|
||||
android:right="1dp"
|
||||
android:bottom="1dp"
|
||||
android:top="1dp" />
|
||||
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
@ -12,7 +12,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:background="@drawable/info_panel_rounded_corner"
|
||||
android:gravity="left"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
@ -49,7 +49,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:background="@drawable/info_panel_rounded_corner"
|
||||
android:gravity="left"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/ipLayout">
|
||||
|
@ -9,7 +9,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleX="0.4"
|
||||
android:scaleY="0.4"
|
||||
android:background="@color/white"
|
||||
android:background="@drawable/checkbox_rounded_corner"
|
||||
android:layout_marginStart="5dp">
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox"
|
||||
@ -19,7 +19,8 @@
|
||||
android:scaleX="3"
|
||||
android:scaleY="3"
|
||||
android:layout_margin="10dp"
|
||||
android:background="@android:color/transparent"/>
|
||||
android:background="@android:color/transparent"
|
||||
android:checked="false"/>
|
||||
</FrameLayout>
|
||||
<ImageView
|
||||
android:id="@+id/countryFlag"
|
||||
|
Loading…
Reference in New Issue
Block a user