Client: cross-platform app (tested on OSX and Android)
diff --git a/core/client/android/app/build.gradle b/core/client/android/app/build.gradle
index 44fe4cf..9102497 100644
--- a/core/client/android/app/build.gradle
+++ b/core/client/android/app/build.gradle
@@ -36,6 +36,7 @@
implementation "androidx.activity:activity:1.3.1"
implementation 'com.google.code.gson:gson:2.8.9'
+ implementation ':pcloud@aar'
// Desugaring and multidex is required for API < 21.
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
diff --git a/core/client/android/app/src/main/AndroidManifest.xml b/core/client/android/app/src/main/AndroidManifest.xml
index 24728da..a75444d 100644
--- a/core/client/android/app/src/main/AndroidManifest.xml
+++ b/core/client/android/app/src/main/AndroidManifest.xml
@@ -4,9 +4,10 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
- <!--uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /-->
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
+ android:name=".PCloudApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@@ -15,14 +16,20 @@
android:theme="@style/Theme.Pcloud"
android:hardwareAccelerated="true">
<activity
- android:name=".MainActivity"
+ android:name=".PCloudActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <service android:name=".PCloudVPNService"
+ android:permission="android.permission.BIND_VPN_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.net.VpnService"/>
+ </intent-filter>
+ </service>
</application>
</manifest>
\ No newline at end of file
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/Base64TypeAdapter.java b/core/client/android/app/src/main/java/me/lekva/pcloud/Base64TypeAdapter.java
deleted file mode 100644
index eda2c58..0000000
--- a/core/client/android/app/src/main/java/me/lekva/pcloud/Base64TypeAdapter.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package me.lekva.pcloud;
-
-import android.os.Build;
-import android.util.Base64;
-
-import androidx.annotation.RequiresApi;
-
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-
-import java.io.IOException;
-
-public class Base64TypeAdapter extends TypeAdapter<byte[]> {
- @RequiresApi(api = Build.VERSION_CODES.O)
- @Override
- public void write(JsonWriter out, byte[] value) throws IOException {
- String val = Base64.encodeToString(value, Base64.NO_WRAP);
- // out.value(val.substring(0, val.length() - 1));
- out.value(val);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.O)
- @Override
- public byte[] read(JsonReader in) throws IOException {
- return Base64.decode(in.nextString(), Base64.NO_WRAP);
- }
-}
\ No newline at end of file
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/MainActivity.java b/core/client/android/app/src/main/java/me/lekva/pcloud/MainActivity.java
deleted file mode 100644
index 4b62246..0000000
--- a/core/client/android/app/src/main/java/me/lekva/pcloud/MainActivity.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package me.lekva.pcloud;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.View;
-
-import androidx.activity.result.ActivityResultLauncher;
-import androidx.annotation.RequiresApi;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.journeyapps.barcodescanner.ScanContract;
-import com.journeyapps.barcodescanner.ScanOptions;
-
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-
-public class MainActivity extends AppCompatActivity {
- private final ActivityResultLauncher<ScanOptions> barcodeLauncher = registerForActivityResult(new ScanContract(),
- result -> {
- if(result.getContents() != null) {
- Gson gson = new GsonBuilder().disableHtmlEscaping().create();
- VPNApiServerConfig config = gson.fromJson(result.getContents(), VPNApiServerConfig.class);
- join(config);
- }
- });
-
- private void join(VPNApiServerConfig config) {
- new Thread(() -> {
- VerifyRequest req = new VerifyRequest();
- req.message = config.message;
- req.signature = config.signature;
- Gson gson = new GsonBuilder().disableHtmlEscaping().create();
- byte[] data = gson.toJson(req).getBytes(StandardCharsets.UTF_8);
- HttpURLConnection urlConnection = null;
- try {
- URL url = new URL(config.address + "/api/verify");
- urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setRequestMethod("POST");
- urlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
- urlConnection.setRequestProperty("Connection", "close");
-
- urlConnection.setInstanceFollowRedirects(false);
- urlConnection.setDoOutput(true);
- urlConnection.setFixedLengthStreamingMode(data.length);
-
- OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
- out.write(data);
- out.flush();
- out.close();
- System.out.println(urlConnection.getResponseCode());
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- urlConnection.disconnect();
- }
- }).start();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- Activity act = this;
- findViewById(R.id.scan_qr_code).setOnClickListener(new View.OnClickListener() {
- @RequiresApi(api = Build.VERSION_CODES.M)
- @Override
- public void onClick(View view) {
- if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
- System.out.println("fooooooo");
- ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.INTERNET}, 20);
- }
-
- ScanOptions options = new ScanOptions();
- options.setDesiredBarcodeFormats(ScanOptions.QR_CODE);
- options.setPrompt("Join PCloud network");
- options.setCameraId(0); // Use a specific camera of the device
- options.setBeepEnabled(false);
- options.setBarcodeImageEnabled(false);
- barcodeLauncher.launch(options);
- }
- });
- }
-}
\ No newline at end of file
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudActivity.java b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudActivity.java
new file mode 100644
index 0000000..3e737d4
--- /dev/null
+++ b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudActivity.java
@@ -0,0 +1,82 @@
+package me.lekva.pcloud;
+
+import android.content.res.Configuration;
+import android.os.Bundle;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.journeyapps.barcodescanner.ScanContract;
+import com.journeyapps.barcodescanner.ScanOptions;
+
+import org.gioui.GioView;
+
+public class PCloudActivity extends AppCompatActivity {
+ private GioView view;
+
+ private final ActivityResultLauncher<ScanOptions> barcodeLauncher = registerForActivityResult(new ScanContract(),
+ result -> {
+ if(result.getContents() != null) {
+ qrcodeScanned(result.getContents());
+ }
+ });
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ view = new GioView(this);
+ setContentView(view);
+ qrcodeScanned("yayaya");
+ }
+
+ @Override
+ public void onDestroy() {
+ view.destroy();
+ super.onDestroy();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ view.start();
+ }
+
+ @Override
+ public void onStop() {
+ view.stop();
+ super.onStop();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration c) {
+ super.onConfigurationChanged(c);
+ view.configurationChanged();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ view.onLowMemory();
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (!view.backPressed())
+ super.onBackPressed();
+ }
+
+ // TODO(giolekva): return void instead of String
+ public String launchBarcodeScanner() {
+ ScanOptions options = new ScanOptions();
+ options.setDesiredBarcodeFormats(ScanOptions.QR_CODE);
+ options.setPrompt("Join PCloud network");
+ options.setCameraId(0); // Use a specific camera of the device
+ options.setBeepEnabled(true);
+ options.setBarcodeImageEnabled(false);
+ barcodeLauncher.launch(options);
+ return null;
+ }
+
+ private native void qrcodeScanned(String contents);
+}
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudApp.java b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudApp.java
new file mode 100644
index 0000000..d8b5723
--- /dev/null
+++ b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudApp.java
@@ -0,0 +1,15 @@
+package me.lekva.pcloud;
+
+import android.app.Application;
+
+import org.gioui.Gio;
+
+public class PCloudApp extends Application {
+ @Override
+ public void onCreate() {
+ System.out.println("fooo");
+ super.onCreate();
+ Gio.init(this);
+ System.out.println("bar");
+ }
+}
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudVPNService.java b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudVPNService.java
new file mode 100644
index 0000000..43ce99f
--- /dev/null
+++ b/core/client/android/app/src/main/java/me/lekva/pcloud/PCloudVPNService.java
@@ -0,0 +1,55 @@
+package me.lekva.pcloud;
+
+import android.app.Service;
+import android.content.Intent;
+import android.net.VpnService;
+import android.os.Handler;
+import android.os.Message;
+
+import androidx.annotation.NonNull;
+
+public class PCloudVPNService extends VpnService implements Handler.Callback {
+ public static final String ACTION_CONNECT = "CONNECT";
+ public static final String ACTION_DISCONNECT = "DISCONNECT";
+
+ private boolean running = false;
+ private Handler handler = null;
+
+ @Override
+ public void onCreate() {
+ if (handler == null) {
+ handler = new Handler(this);
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent != null && intent.getAction().equals(ACTION_DISCONNECT)) {
+ stopVpn();
+ return Service.START_NOT_STICKY;
+ } else {
+ startVpn();
+ return Service.START_STICKY;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ stopVpn();
+ }
+
+ private void startVpn() {
+ System.out.println("--- START");
+ }
+
+ private void stopVpn() {
+ System.out.println("--- STOP");
+ running = false;
+ }
+
+ @Override
+ public boolean handleMessage(@NonNull Message message) {
+ System.out.println(getString(message.what));
+ return true;
+ }
+}
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/VPNApiServerConfig.java b/core/client/android/app/src/main/java/me/lekva/pcloud/VPNApiServerConfig.java
deleted file mode 100644
index 0128a76..0000000
--- a/core/client/android/app/src/main/java/me/lekva/pcloud/VPNApiServerConfig.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package me.lekva.pcloud;
-
-import com.google.gson.annotations.JsonAdapter;
-import com.google.gson.annotations.SerializedName;
-
-public class VPNApiServerConfig {
- @SerializedName("vpn_api_addr")
- public String address;
- @JsonAdapter(Base64TypeAdapter.class)
- public byte[] message;
- @JsonAdapter(Base64TypeAdapter.class)
- public byte[] signature;
-}
diff --git a/core/client/android/app/src/main/java/me/lekva/pcloud/VerifyRequest.java b/core/client/android/app/src/main/java/me/lekva/pcloud/VerifyRequest.java
deleted file mode 100644
index 7feaef1..0000000
--- a/core/client/android/app/src/main/java/me/lekva/pcloud/VerifyRequest.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package me.lekva.pcloud;
-
-import com.google.gson.annotations.JsonAdapter;
-
-public class VerifyRequest {
- @JsonAdapter(Base64TypeAdapter.class)
- public byte[] message;
- @JsonAdapter(Base64TypeAdapter.class)
- public byte[] signature;
-}
diff --git a/core/client/android/settings.gradle b/core/client/android/settings.gradle
index f75bfc8..c030043 100644
--- a/core/client/android/settings.gradle
+++ b/core/client/android/settings.gradle
@@ -4,6 +4,9 @@
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
+ flatDir {
+ dirs 'app/libs'
+ }
}
}
rootProject.name = "pcloud"