mirror of
https://github.com/yggdrasil-network/crispa-android.git
synced 2025-01-22 16:06:30 +00:00
1. fixed service stop
2. created layout
This commit is contained in:
parent
04cc088f4d
commit
eb480c2677
@ -6,7 +6,7 @@ android {
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "io.github.chronosx88.yggdrasil"
|
||||
minSdkVersion 21
|
||||
minSdkVersion 22
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
@ -24,10 +24,8 @@
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -4,48 +4,55 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.os.Bundle
|
||||
import android.widget.Button
|
||||
import android.util.Log
|
||||
import android.widget.RadioGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private var isYggStarted = false
|
||||
companion object {
|
||||
private const val TAG="Yggdrasil";
|
||||
private const val VPN_REQUEST_CODE = 0x0F
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
val connectButton = findViewById<Button>(R.id.connect_button)
|
||||
connectButton.setOnClickListener {
|
||||
if(!isYggStarted) {
|
||||
// Prepare to establish a VPN connection.
|
||||
// This method returns null if the VPN application is already prepared
|
||||
// or if the user has previously consented to the VPN application.
|
||||
// Otherwise, it returns an Intent to a system activity.
|
||||
val vpnIntent = VpnService.prepare(this)
|
||||
if (vpnIntent != null) startActivityForResult(
|
||||
vpnIntent,
|
||||
0x0F
|
||||
)
|
||||
else onActivityResult(0x0F, Activity.RESULT_OK, null)
|
||||
} else {
|
||||
// FIXME fix this shit, this code doesn't stop service for some reasons
|
||||
val intent = Intent(this, YggdrasilTunService::class.java)
|
||||
stopService(intent)
|
||||
connectButton.text = "Connect"
|
||||
isYggStarted = false
|
||||
val connectRadioGroup = findViewById<RadioGroup>(R.id.connectRadioGroup)
|
||||
connectRadioGroup.setOnCheckedChangeListener(
|
||||
RadioGroup.OnCheckedChangeListener { group, checkedId ->
|
||||
when (checkedId) {
|
||||
R.id.disconnectButton -> stopVpn()
|
||||
R.id.connectButton -> startVpn()
|
||||
else -> { // Note the block
|
||||
//print("x is neither 1 nor 2")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun stopVpn(){
|
||||
Log.d(TAG,"Stop")
|
||||
val intent = Intent(this, YggdrasilTunService::class.java)
|
||||
intent.putExtra("COMMAND", "STOP")
|
||||
startService(intent)
|
||||
}
|
||||
|
||||
fun startVpn(){
|
||||
Log.d(TAG,"Start")
|
||||
val intent= VpnService.prepare(this)
|
||||
if (intent!=null){
|
||||
startActivityForResult(intent, VPN_REQUEST_CODE);
|
||||
}else{
|
||||
onActivityResult(VPN_REQUEST_CODE, Activity.RESULT_OK, null);
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == 0x0F && resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == VPN_REQUEST_CODE && resultCode== Activity.RESULT_OK){
|
||||
val intent = Intent(this, YggdrasilTunService::class.java)
|
||||
startService(intent)
|
||||
val connectButton = findViewById<Button>(R.id.connect_button)
|
||||
connectButton.text = "Disconnect"
|
||||
isYggStarted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package io.github.chronosx88.yggdrasil
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.VpnService
|
||||
import android.os.ParcelFileDescriptor
|
||||
import com.google.gson.Gson
|
||||
@ -36,7 +39,9 @@ class YggdrasilTunService : VpnService() {
|
||||
private lateinit var writeCoroutine: CoroutineContext
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
if (intent?.getStringExtra("COMMAND") == "STOP") {
|
||||
stopVpn()
|
||||
}
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
@ -83,6 +88,22 @@ class YggdrasilTunService : VpnService() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNonVpnNetworks(Address: String): Array<Network> {
|
||||
val cm =
|
||||
getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val networks = cm.allNetworks
|
||||
for (network in networks) {
|
||||
val linkProperties = cm.getLinkProperties(network)
|
||||
val addresses = linkProperties.linkAddresses
|
||||
for (addr in addresses) {
|
||||
if (addr.toString().startsWith(Address)) {
|
||||
return arrayOf(network)
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptyArray<Network>()
|
||||
}
|
||||
|
||||
private fun fixConfig(config: MutableMap<Any?, Any?>): MutableMap<Any?, Any?> {
|
||||
val peers = arrayListOf<String>();
|
||||
peers.add("tcp://194.177.21.156:5066")
|
||||
@ -123,26 +144,14 @@ class YggdrasilTunService : VpnService() {
|
||||
// Read the outgoing packet from the input stream.
|
||||
var length = tunInputStream!!.read(packet)
|
||||
|
||||
//System.out.println("packet size:"+packet.size+" "+byteArrayToHex(packet))
|
||||
//System.out.println("buffer size:"+buffer.array().size+" "+byteArrayToHex(buffer.array()))
|
||||
if (length > 0) {
|
||||
// Ignore control messages, which start with zero.
|
||||
if (packet.get(0).compareTo(0)!=0) {
|
||||
var buffer = ByteBuffer.allocate(length);
|
||||
buffer.put(packet, 0, length)
|
||||
buffer.limit(length)
|
||||
yggConduitEndpoint.send(buffer.array())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isBufferEmpty(buffer: ByteArray): Boolean {
|
||||
var sum: Byte = 0
|
||||
for (i in buffer) {
|
||||
sum.or(i)
|
||||
}
|
||||
return sum == 0.toByte()
|
||||
}
|
||||
}
|
||||
|
||||
private fun writePacketsToTun() {
|
||||
@ -152,12 +161,17 @@ class YggdrasilTunService : VpnService() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRevoke() {
|
||||
super.onRevoke()
|
||||
fun stopVpn() {
|
||||
isRunning = false
|
||||
readCoroutine.cancel()
|
||||
writeCoroutine.cancel()
|
||||
tunInterface!!.close()
|
||||
tunInterface = null
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
|
8
app/src/main/res/drawable/pink_out_line.xml
Normal file
8
app/src/main/res/drawable/pink_out_line.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="2dp" />
|
||||
<solid android:color="#80000000" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/green" />
|
||||
</shape>
|
6
app/src/main/res/drawable/toggle_widget_background.xml
Normal file
6
app/src/main/res/drawable/toggle_widget_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/pink" android:state_checked="true" />
|
||||
<item android:drawable="@color/dark_pink" android:state_pressed="true" />
|
||||
<item android:drawable="@color/transparent" />
|
||||
</selector>
|
@ -1,18 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity" android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:background="@color/grey"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<Button
|
||||
android:id="@+id/connect_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
<RadioGroup
|
||||
android:id="@+id/connectRadioGroup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="@drawable/pink_out_line"
|
||||
android:checkedButton="@+id/offer"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteX="50dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/disconnectButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="1dp"
|
||||
android:layout_marginTop="1dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/toggle_widget_background"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:text="@string/disconnect_button"
|
||||
android:textColor="@color/white"
|
||||
android:checked="true"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/connectButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="1dp"
|
||||
android:layout_marginRight="1dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/toggle_widget_background"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:text="@string/connect_button"
|
||||
android:layout_gravity="center"/>
|
||||
android:textColor="@color/white" />
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorPrimary">#555555</color>
|
||||
<color name="colorPrimaryDark">#343334</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
<color name="white">#ffffff</color>
|
||||
<color name="green">#83cf03</color>
|
||||
<color name="grey">#343334</color>
|
||||
<color name="transparent">#555555</color>
|
||||
<color name="dark_pink">#666666</color>
|
||||
<color name="pink">#777777</color>
|
||||
</resources>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Yggdrasil</string>
|
||||
<string name="connect_button">Connect</string>
|
||||
<string name="disconnect_button">Disconnect</string>
|
||||
</resources>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user