client-android: store network config as app prefs
diff --git a/core/client/android/app/build.gradle b/core/client/android/app/build.gradle
index 9102497..6a8c04f 100644
--- a/core/client/android/app/build.gradle
+++ b/core/client/android/app/build.gradle
@@ -47,4 +47,5 @@
implementation 'androidx.camera:camera-core:1.1.0-alpha11'
implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha11'
implementation 'androidx.camera:camera-view:1.0.0-alpha31'
+ implementation "androidx.security:security-crypto:1.1.0-alpha03"
}
\ No newline at end of file
diff --git a/core/client/android/app/src/main/AndroidManifest.xml b/core/client/android/app/src/main/AndroidManifest.xml
index a75444d..ccdff2c 100644
--- a/core/client/android/app/src/main/AndroidManifest.xml
+++ b/core/client/android/app/src/main/AndroidManifest.xml
@@ -5,6 +5,7 @@
<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.FOREGROUND_SERVICE" />
<application
android:name=".PCloudApp"
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
index 330e8cd..5e7dedd 100644
--- 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
@@ -81,18 +81,15 @@
return null;
}
- public String startVpn(String ipCidr) {
+ public void startVpn() {
Intent intent = VpnService.prepare(this);
if (intent != null) {
- System.out.println("#### STARTVPN");
intent.setAction(PCloudVPNService.ACTION_CONNECT);
startActivityForResult(intent, VPN_START_CODE);
} else {
intent = new Intent(this, PCloudVPNService.class);
startService(intent);
}
-
- 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
index 1e2b64a..b7647db 100644
--- 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
@@ -1,13 +1,66 @@
package me.lekva.pcloud;
import android.app.Application;
+import android.app.NotificationChannel;
+import android.content.SharedPreferences;
+import android.os.Build;
+
+import androidx.core.app.NotificationManagerCompat;
+import androidx.security.crypto.EncryptedSharedPreferences;
+import androidx.security.crypto.MasterKey;
import org.gioui.Gio;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
public class PCloudApp extends Application {
+ static final String STATUS_CHANNEL_ID = "pcloud-status";
+ static final int STATUS_NOTIFICATION_ID = 1;
+
+ static final String NOTIFY_CHANNEL_ID = "pcloud-notify";
+ static final int NOTIFY_NOTIFICATION_ID = 2;
+
@Override
public void onCreate() {
super.onCreate();
Gio.init(this);
+
+ createNotificationChannel(NOTIFY_CHANNEL_ID, "Notifications", NotificationManagerCompat.IMPORTANCE_DEFAULT);
+ createNotificationChannel(STATUS_CHANNEL_ID, "VPN Status", NotificationManagerCompat.IMPORTANCE_LOW);
+ }
+
+ private void createNotificationChannel(String id, String name, int importance) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ return;
+ }
+ NotificationChannel channel = new NotificationChannel(id, name, importance);
+ NotificationManagerCompat nm = NotificationManagerCompat.from(this);
+ nm.createNotificationChannel(channel);
+ }
+
+ // encryptToPref a byte array of data using the Jetpack Security
+ // library and writes it to a global encrypted preference store.
+ public void encryptToPref(String prefKey, String plaintext) throws IOException, GeneralSecurityException {
+ getEncryptedPrefs().edit().putString(prefKey, plaintext).commit();
+ }
+
+ // decryptFromPref decrypts a encrypted preference using the Jetpack Security
+ // library and returns the plaintext.
+ public String decryptFromPref(String prefKey) throws IOException, GeneralSecurityException {
+ return getEncryptedPrefs().getString(prefKey, null);
+ }
+
+ private SharedPreferences getEncryptedPrefs() throws IOException, GeneralSecurityException {
+ MasterKey key = new MasterKey.Builder(this)
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
+ .build();
+ return EncryptedSharedPreferences.create(
+ this,
+ "secret_shared_prefs",
+ key,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ );
}
}
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
index 1566ed1..91a4a38 100644
--- 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
@@ -10,11 +10,15 @@
import android.system.OsConstants;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.core.app.NotificationCompat;
public class PCloudVPNService extends VpnService implements Handler.Callback {
public static final String ACTION_CONNECT = "CONNECT";
public static final String ACTION_DISCONNECT = "DISCONNECT";
+ private PendingIntent configureIntent;
+
private boolean running = false;
private Handler handler = null;
@@ -23,6 +27,9 @@
if (handler == null) {
handler = new Handler(this);
}
+
+ configureIntent = PendingIntent.getActivity(this, 0, new Intent(this, PCloudActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
@@ -41,8 +48,10 @@
stopVpn();
}
+ @RequiresApi(api = Build.VERSION_CODES.O)
private void startVpn() {
System.out.println("--- START");
+ updateForegroundNotification();
connect();
}
@@ -73,6 +82,15 @@
return builder;
}
+ private void updateForegroundNotification() {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this, PCloudApp.STATUS_CHANNEL_ID)
+ .setContentTitle("PCloud")
+ .setContentText("hiiii")
+ .setContentIntent(configureIntent)
+ .setPriority(NotificationCompat.PRIORITY_LOW);
+ startForeground(PCloudApp.STATUS_NOTIFICATION_ID, builder.build());
+ }
+
private native void connect();
private native void disconnect();
}