fix acceptinvalidcerts
This commit is contained in:
parent
eb3f3afa60
commit
8dee1c7ee5
@ -0,0 +1,146 @@
|
|||||||
|
package software.eskimo.capacitor.sockets;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import com.getcapacitor.JSObject;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class SocketForegroundService extends Service {
|
||||||
|
private static final String TAG = "SocketForegroundService";
|
||||||
|
|
||||||
|
// Default values
|
||||||
|
private static final String DEFAULT_CHANNEL_ID = "socket_service_channel";
|
||||||
|
private static final String DEFAULT_CHANNEL_NAME = "Socket Connection";
|
||||||
|
private static final String DEFAULT_NOTIFICATION_TITLE = "Connected to Server";
|
||||||
|
private static final String DEFAULT_NOTIFICATION_TEXT = "Tap to open";
|
||||||
|
private static final int DEFAULT_NOTIFICATION_ID = 1001;
|
||||||
|
|
||||||
|
// Configurable values
|
||||||
|
private String channelId = DEFAULT_CHANNEL_ID;
|
||||||
|
private String channelName = DEFAULT_CHANNEL_NAME;
|
||||||
|
private String notificationTitle = DEFAULT_NOTIFICATION_TITLE;
|
||||||
|
private String notificationText = DEFAULT_NOTIFICATION_TEXT;
|
||||||
|
private int notificationId = DEFAULT_NOTIFICATION_ID;
|
||||||
|
private int notificationIcon = android.R.drawable.ic_dialog_info;
|
||||||
|
private boolean running = false;
|
||||||
|
|
||||||
|
private final IBinder binder = new LocalBinder();
|
||||||
|
|
||||||
|
public class LocalBinder extends Binder {
|
||||||
|
SocketForegroundService getService() {
|
||||||
|
return SocketForegroundService.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
if (intent != null) {
|
||||||
|
channelId = intent.getStringExtra("channelId") != null ?
|
||||||
|
intent.getStringExtra("channelId") : DEFAULT_CHANNEL_ID;
|
||||||
|
channelName = intent.getStringExtra("channelName") != null ?
|
||||||
|
intent.getStringExtra("channelName") : DEFAULT_CHANNEL_NAME;
|
||||||
|
notificationTitle = intent.getStringExtra("notificationTitle") != null ?
|
||||||
|
intent.getStringExtra("notificationTitle") : DEFAULT_NOTIFICATION_TITLE;
|
||||||
|
notificationText = intent.getStringExtra("notificationText") != null ?
|
||||||
|
intent.getStringExtra("notificationText") : DEFAULT_NOTIFICATION_TEXT;
|
||||||
|
notificationId = intent.getIntExtra("notificationId", DEFAULT_NOTIFICATION_ID);
|
||||||
|
notificationIcon = intent.getIntExtra("notificationIcon", notificationIcon);
|
||||||
|
|
||||||
|
Log.d(TAG, "Starting foreground service with: " +
|
||||||
|
"channelId=" + channelId +
|
||||||
|
", title=" + notificationTitle +
|
||||||
|
", text=" + notificationText);
|
||||||
|
|
||||||
|
startForeground();
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Intent was null in onStartCommand");
|
||||||
|
}
|
||||||
|
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startForeground() {
|
||||||
|
if (running) {
|
||||||
|
Log.d(TAG, "Service already running, not starting again");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
createNotificationChannel();
|
||||||
|
|
||||||
|
Intent notificationIntent = getPackageManager()
|
||||||
|
.getLaunchIntentForPackage(getPackageName());
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(
|
||||||
|
this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
|
||||||
|
Log.d(TAG, "Building notification with title: " + notificationTitle);
|
||||||
|
|
||||||
|
Notification notification = new NotificationCompat.Builder(this, channelId)
|
||||||
|
.setContentTitle(notificationTitle)
|
||||||
|
.setContentText(notificationText)
|
||||||
|
.setSmallIcon(notificationIcon)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setOngoing(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
startForeground(notificationId, notification);
|
||||||
|
running = true;
|
||||||
|
Log.d(TAG, "Foreground service started with notification ID: " + notificationId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in startForeground", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateNotification(String title, String text) {
|
||||||
|
if (!running) return;
|
||||||
|
|
||||||
|
NotificationManager notificationManager =
|
||||||
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
Notification notification = new NotificationCompat.Builder(this, channelId)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(text)
|
||||||
|
.setSmallIcon(notificationIcon)
|
||||||
|
.setContentIntent(PendingIntent.getActivity(
|
||||||
|
this, 0,
|
||||||
|
getPackageManager().getLaunchIntentForPackage(getPackageName()),
|
||||||
|
PendingIntent.FLAG_IMMUTABLE))
|
||||||
|
.setOngoing(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
notificationManager.notify(notificationId, notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotificationChannel() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
NotificationChannel channel = new NotificationChannel(
|
||||||
|
channelId,
|
||||||
|
channelName,
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
);
|
||||||
|
|
||||||
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
running = false;
|
||||||
|
Log.d(TAG, "Foreground service stopped");
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,23 @@
|
|||||||
package software.eskimo.capacitor.sockets;
|
package software.eskimo.capacitor.sockets;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.SecureRandom;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLParameters;
|
||||||
|
import javax.net.ssl.SSLSocket;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import java.io.IOException;
|
import javax.net.ssl.SNIHostName;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
import java.security.cert.X509Certificate;
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public class SocketHandler {
|
public class SocketHandler {
|
||||||
private String id;
|
private String id;
|
||||||
@ -33,39 +39,58 @@ public class SocketHandler {
|
|||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
delegate.onStateChanged(id, "connecting");
|
delegate.onStateChanged(id, "connecting");
|
||||||
|
|
||||||
if (useTLS) {
|
if (useTLS) {
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
|
||||||
if (acceptInvalidCertificates) {
|
if (acceptInvalidCertificates) {
|
||||||
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
|
sslContext.init(null, new TrustManager[]{new InsecureTrustAllManager()}, new java.security.SecureRandom());
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
|
|
||||||
}}, new java.security.SecureRandom());
|
|
||||||
} else {
|
} else {
|
||||||
sslContext.init(null, null, new java.security.SecureRandom());
|
sslContext.init(null, null, new java.security.SecureRandom());
|
||||||
}
|
}
|
||||||
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
|
|
||||||
socket = socketFactory.createSocket(host, port);
|
SSLSocketFactory factory = sslContext.getSocketFactory();
|
||||||
|
SSLSocket sslSocket = (SSLSocket) factory.createSocket();
|
||||||
|
|
||||||
|
if (acceptInvalidCertificates) {
|
||||||
|
java.net.InetAddress addr = java.net.InetAddress.getByName(host);
|
||||||
|
sslSocket.connect(new java.net.InetSocketAddress(addr, port));
|
||||||
|
} else {
|
||||||
|
sslSocket.connect(new java.net.InetSocketAddress(host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
javax.net.ssl.SSLParameters params = sslSocket.getSSLParameters();
|
||||||
|
try {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= 24) {
|
||||||
|
params.setServerNames(java.util.Collections.singletonList(new javax.net.ssl.SNIHostName(host)));
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
|
||||||
|
if (acceptInvalidCertificates) {
|
||||||
|
params.setEndpointIdentificationAlgorithm(null);
|
||||||
|
} else {
|
||||||
|
params.setEndpointIdentificationAlgorithm("HTTPS");
|
||||||
|
}
|
||||||
|
sslSocket.setSSLParameters(params);
|
||||||
|
|
||||||
|
sslSocket.startHandshake();
|
||||||
|
socket = sslSocket;
|
||||||
} else {
|
} else {
|
||||||
socket = new Socket(host, port);
|
socket = new java.net.Socket(host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate.onStateChanged(id, "connected");
|
delegate.onStateChanged(id, "connected");
|
||||||
outputStream = socket.getOutputStream();
|
outputStream = socket.getOutputStream();
|
||||||
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
inputStream = new java.io.BufferedReader(new java.io.InputStreamReader(socket.getInputStream()));
|
||||||
receive();
|
receive();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("SocketHandler", "Connection error: " + e.getMessage(), e);
|
android.util.Log.e("SocketHandler", "Connection error: " + e.getMessage(), e);
|
||||||
delegate.onStateChanged(id, "disconnected");
|
delegate.onStateChanged(id, "disconnected");
|
||||||
|
closeQuietly();
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void send(String message) {
|
public void send(String message) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
@ -76,6 +101,7 @@ public class SocketHandler {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("SocketHandler", "Send error: " + e.getMessage(), e);
|
Log.e("SocketHandler", "Send error: " + e.getMessage(), e);
|
||||||
delegate.onStateChanged(id, "disconnected");
|
delegate.onStateChanged(id, "disconnected");
|
||||||
|
closeQuietly();
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
@ -101,23 +127,35 @@ public class SocketHandler {
|
|||||||
while ((numCharsRead = inputStream.read(buffer)) != -1) {
|
while ((numCharsRead = inputStream.read(buffer)) != -1) {
|
||||||
messageBuilder.append(buffer, 0, numCharsRead);
|
messageBuilder.append(buffer, 0, numCharsRead);
|
||||||
String message = messageBuilder.toString();
|
String message = messageBuilder.toString();
|
||||||
|
|
||||||
// Check if the message ends with \r\n (or \n, depending on protocol)
|
|
||||||
if (message.endsWith("\r\n")) {
|
if (message.endsWith("\r\n")) {
|
||||||
Log.d("SocketHandler", "Message received: " + message);
|
Log.d("SocketHandler", "Message received: " + message);
|
||||||
delegate.onMessageReceived(id, message); // Notify with full message including \r\n
|
delegate.onMessageReceived(id, message);
|
||||||
messageBuilder.setLength(0); // Clear the buffer for the next message
|
messageBuilder.setLength(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("SocketHandler", "Receive error: " + e.getMessage(), e);
|
Log.e("SocketHandler", "Receive error: " + e.getMessage(), e);
|
||||||
delegate.onStateChanged(id, "disconnected");
|
delegate.onStateChanged(id, "disconnected");
|
||||||
|
} finally {
|
||||||
|
closeQuietly();
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void closeQuietly() {
|
||||||
|
try {
|
||||||
|
if (socket != null) socket.close();
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
public interface SocketDelegate {
|
public interface SocketDelegate {
|
||||||
void onStateChanged(String socketId, String state);
|
void onStateChanged(String socketId, String state);
|
||||||
void onMessageReceived(String socketId, String message);
|
void onMessageReceived(String socketId, String message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class InsecureTrustAllManager implements X509TrustManager {
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
|
||||||
|
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user