add notification text for foreground service
This commit is contained in:
		
							parent
							
								
									152a31f876
								
							
						
					
					
						commit
						9a2f7a4735
					
				
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								README.md
									
									
									
									
									
								
							@ -18,6 +18,7 @@ npx cap sync
 | 
				
			|||||||
* [`send(...)`](#send)
 | 
					* [`send(...)`](#send)
 | 
				
			||||||
* [`disconnect(...)`](#disconnect)
 | 
					* [`disconnect(...)`](#disconnect)
 | 
				
			||||||
* [`close(...)`](#close)
 | 
					* [`close(...)`](#close)
 | 
				
			||||||
 | 
					* [`setNotificationText(...)`](#setnotificationtext)
 | 
				
			||||||
* [`addListener('state', ...)`](#addlistenerstate-)
 | 
					* [`addListener('state', ...)`](#addlistenerstate-)
 | 
				
			||||||
* [`addListener('message', ...)`](#addlistenermessage-)
 | 
					* [`addListener('message', ...)`](#addlistenermessage-)
 | 
				
			||||||
* [Interfaces](#interfaces)
 | 
					* [Interfaces](#interfaces)
 | 
				
			||||||
@ -43,12 +44,12 @@ create(options: { id: string; }) => Promise<void>
 | 
				
			|||||||
### connect(...)
 | 
					### connect(...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```typescript
 | 
					```typescript
 | 
				
			||||||
connect(options: { id: string; host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean; }) => Promise<void>
 | 
					connect(options: { id: string; host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean; delimiter?: string; }) => Promise<void>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Param         | Type                                                                                                            |
 | 
					| Param         | Type                                                                                                                                |
 | 
				
			||||||
| ------------- | --------------------------------------------------------------------------------------------------------------- |
 | 
					| ------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
 | 
				
			||||||
| **`options`** | <code>{ id: string; host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean; }</code> |
 | 
					| **`options`** | <code>{ id: string; host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean; delimiter?: string; }</code> |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--------------------
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,6 +93,19 @@ close(options: { id: string; }) => Promise<void>
 | 
				
			|||||||
--------------------
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### setNotificationText(...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```typescript
 | 
				
			||||||
 | 
					setNotificationText(options: { notificationText: string; }) => Promise<void>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					| Param         | Type                                       |
 | 
				
			||||||
 | 
					| ------------- | ------------------------------------------ |
 | 
				
			||||||
 | 
					| **`options`** | <code>{ notificationText: string; }</code> |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### addListener('state', ...)
 | 
					### addListener('state', ...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```typescript
 | 
					```typescript
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,12 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
	<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 | 
					    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 | 
				
			||||||
	<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
 | 
					    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 | 
				
			||||||
    <application>
 | 
					    <application>
 | 
				
			||||||
        <service
 | 
					        <service
 | 
				
			||||||
		    android:name=".SocketForegroundService"
 | 
					            android:name="software.eskimo.capacitor.sockets.SocketForegroundService"
 | 
				
			||||||
		    android:enabled="true"
 | 
					            android:enabled="true"
 | 
				
			||||||
		    android:exported="false"
 | 
					            android:exported="false"
 | 
				
			||||||
		    android:foregroundServiceType="dataSync" />
 | 
					            android:foregroundServiceType="connectedDevice" />
 | 
				
			||||||
    </application>
 | 
					    </application>
 | 
				
			||||||
</manifest>
 | 
					</manifest>
 | 
				
			||||||
@ -14,7 +14,8 @@ import android.util.Log;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class SocketForegroundService extends Service {
 | 
					public class SocketForegroundService extends Service {
 | 
				
			||||||
    private static final String CHANNEL_ID = "socket_channel";
 | 
					    private static final String CHANNEL_ID = "socket_channel";
 | 
				
			||||||
    private static final String CHANNEL_NAME = "Socket Service Channel";
 | 
					    private static final String CHANNEL_NAME = "Socket Service";
 | 
				
			||||||
 | 
					    private static final int NOTIFICATION_ID = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onCreate() {
 | 
					    public void onCreate() {
 | 
				
			||||||
@ -24,7 +25,20 @@ public class SocketForegroundService extends Service {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
					    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
				
			||||||
        // Retrieve the main app's "app_name" string resource
 | 
					        String action = intent != null ? intent.getAction() : null;
 | 
				
			||||||
 | 
					        String notificationText = intent != null ? 
 | 
				
			||||||
 | 
					            intent.getStringExtra("notificationText") : "Maintaining connection";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ("software.eskimo.capacitor.sockets.UPDATE_NOTIFICATION".equals(action)) {
 | 
				
			||||||
 | 
					            updateNotification(notificationText);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            startForegroundWithNotification(notificationText);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return START_STICKY;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void startForegroundWithNotification(String notificationText) {
 | 
				
			||||||
        int appNameResId = getResources().getIdentifier("app_name", "string", getApplicationContext().getPackageName());
 | 
					        int appNameResId = getResources().getIdentifier("app_name", "string", getApplicationContext().getPackageName());
 | 
				
			||||||
        String appName = (appNameResId != 0) ? getString(appNameResId) : "Socket Service";
 | 
					        String appName = (appNameResId != 0) ? getString(appNameResId) : "Socket Service";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -35,18 +49,49 @@ public class SocketForegroundService extends Service {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
 | 
					        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
 | 
				
			||||||
            .setContentTitle(appName)
 | 
					            .setContentTitle(appName)
 | 
				
			||||||
            .setContentText("Background service running")
 | 
					            .setContentText(notificationText)
 | 
				
			||||||
            .setSmallIcon(iconResId)
 | 
					            .setSmallIcon(iconResId)
 | 
				
			||||||
 | 
					            .setPriority(NotificationCompat.PRIORITY_LOW)
 | 
				
			||||||
            .build();
 | 
					            .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 | 
					        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
 | 
				
			||||||
            startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
 | 
					            startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            startForeground(1, notification);
 | 
					            startForeground(NOTIFICATION_ID, notification);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Log.d("SocketForegroundService", "Foreground service started with app name: " + appName);
 | 
					        Log.d("SocketForegroundService", "Foreground service started with app name: " + appName);
 | 
				
			||||||
        return START_STICKY;
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void updateNotification(String notificationText) {
 | 
				
			||||||
 | 
					        int appNameResId = getResources().getIdentifier("app_name", "string", getApplicationContext().getPackageName());
 | 
				
			||||||
 | 
					        String appName = (appNameResId != 0) ? getString(appNameResId) : "Socket Service";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int iconResId = getResources().getIdentifier("ic_notification", "drawable", getApplicationContext().getPackageName());
 | 
				
			||||||
 | 
					        if (iconResId == 0) {
 | 
				
			||||||
 | 
					            iconResId = android.R.drawable.ic_dialog_info;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
 | 
				
			||||||
 | 
					            .setContentTitle(appName)
 | 
				
			||||||
 | 
					            .setContentText(notificationText)
 | 
				
			||||||
 | 
					            .setSmallIcon(iconResId)
 | 
				
			||||||
 | 
					            .setPriority(NotificationCompat.PRIORITY_LOW)
 | 
				
			||||||
 | 
					            .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 | 
				
			||||||
 | 
					        if (notificationManager != null) {
 | 
				
			||||||
 | 
					            notificationManager.notify(NOTIFICATION_ID, notification);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Log.d("SocketForegroundService", "Notification updated with text: " + notificationText);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onTaskRemoved(Intent rootIntent) {
 | 
				
			||||||
 | 
					        Log.d("SocketForegroundService", "App task removed. Stopping foreground service.");
 | 
				
			||||||
 | 
					        stopSelf();
 | 
				
			||||||
 | 
					        super.onTaskRemoved(rootIntent);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void createNotificationChannel() {
 | 
					    private void createNotificationChannel() {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,8 @@ import java.io.IOException;
 | 
				
			|||||||
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.security.cert.X509Certificate;
 | 
				
			||||||
 | 
					import java.util.concurrent.ExecutorService;
 | 
				
			||||||
 | 
					import java.util.concurrent.Executors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class SocketHandler {
 | 
					public class SocketHandler {
 | 
				
			||||||
    private String id;
 | 
					    private String id;
 | 
				
			||||||
@ -19,18 +21,24 @@ public class SocketHandler {
 | 
				
			|||||||
    private OutputStream outputStream;
 | 
					    private OutputStream outputStream;
 | 
				
			||||||
    private BufferedReader inputStream;
 | 
					    private BufferedReader inputStream;
 | 
				
			||||||
    private SocketDelegate delegate;
 | 
					    private SocketDelegate delegate;
 | 
				
			||||||
 | 
					    private String delimiter;
 | 
				
			||||||
 | 
					    private final ExecutorService executor = Executors.newFixedThreadPool(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SocketHandler(String id, SocketDelegate delegate) {
 | 
					    public SocketHandler(String id, SocketDelegate delegate) {
 | 
				
			||||||
        this.id = id;
 | 
					        this.id = id;
 | 
				
			||||||
        this.delegate = delegate;
 | 
					        this.delegate = delegate;
 | 
				
			||||||
 | 
					        this.delimiter = "\r\n"; // Default delimiter
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getId() {
 | 
					    public String getId() {
 | 
				
			||||||
        return id;
 | 
					        return id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void connect(final String host, final int port, final boolean useTLS, final boolean acceptInvalidCertificates) {
 | 
					    public void connect(final String host, final int port, final boolean useTLS, final boolean acceptInvalidCertificates, final String delimiter) {
 | 
				
			||||||
        new Thread(() -> {
 | 
					        if (delimiter != null && !delimiter.isEmpty()) {
 | 
				
			||||||
 | 
					            this.delimiter = delimiter;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        executor.execute(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                delegate.onStateChanged(id, "connecting");
 | 
					                delegate.onStateChanged(id, "connecting");
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
@ -63,11 +71,11 @@ public class SocketHandler {
 | 
				
			|||||||
                Log.e("SocketHandler", "Connection error: " + e.getMessage(), e);
 | 
					                Log.e("SocketHandler", "Connection error: " + e.getMessage(), e);
 | 
				
			||||||
                delegate.onStateChanged(id, "disconnected");
 | 
					                delegate.onStateChanged(id, "disconnected");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).start();
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void send(String message) {
 | 
					    public void send(String message) {
 | 
				
			||||||
        new Thread(() -> {
 | 
					        executor.execute(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                if (outputStream != null) {
 | 
					                if (outputStream != null) {
 | 
				
			||||||
                    outputStream.write(message.getBytes());
 | 
					                    outputStream.write(message.getBytes());
 | 
				
			||||||
@ -77,11 +85,17 @@ public class SocketHandler {
 | 
				
			|||||||
                Log.e("SocketHandler", "Send error: " + e.getMessage(), e);
 | 
					                Log.e("SocketHandler", "Send error: " + e.getMessage(), e);
 | 
				
			||||||
                delegate.onStateChanged(id, "disconnected");
 | 
					                delegate.onStateChanged(id, "disconnected");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).start();
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void disconnect() {
 | 
					    public void disconnect() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 | 
					            if (inputStream != null) {
 | 
				
			||||||
 | 
					                inputStream.close();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (outputStream != null) {
 | 
				
			||||||
 | 
					                outputStream.close();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (socket != null) {
 | 
					            if (socket != null) {
 | 
				
			||||||
                socket.close();
 | 
					                socket.close();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -89,11 +103,16 @@ public class SocketHandler {
 | 
				
			|||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            Log.e("SocketHandler", "Disconnect error: " + e.getMessage(), e);
 | 
					            Log.e("SocketHandler", "Disconnect error: " + e.getMessage(), e);
 | 
				
			||||||
            delegate.onStateChanged(id, "disconnected");
 | 
					            delegate.onStateChanged(id, "disconnected");
 | 
				
			||||||
 | 
					        } finally {
 | 
				
			||||||
 | 
					            inputStream = null;
 | 
				
			||||||
 | 
					            outputStream = null;
 | 
				
			||||||
 | 
					            socket = null;
 | 
				
			||||||
 | 
					            executor.shutdownNow();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void receive() {
 | 
					    private void receive() {
 | 
				
			||||||
        new Thread(() -> {
 | 
					        executor.execute(() -> {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                char[] buffer = new char[1024];
 | 
					                char[] buffer = new char[1024];
 | 
				
			||||||
                StringBuilder messageBuilder = new StringBuilder();
 | 
					                StringBuilder messageBuilder = new StringBuilder();
 | 
				
			||||||
@ -102,18 +121,17 @@ public class SocketHandler {
 | 
				
			|||||||
                    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(delimiter)) {
 | 
				
			||||||
                    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");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).start();
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public interface SocketDelegate {
 | 
					    public interface SocketDelegate {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,10 +7,10 @@ import java.util.List;
 | 
				
			|||||||
public class Sockets implements SocketHandler.SocketDelegate {
 | 
					public class Sockets implements SocketHandler.SocketDelegate {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private List<SocketHandler> sockets = new ArrayList<>();
 | 
					    private List<SocketHandler> sockets = new ArrayList<>();
 | 
				
			||||||
    private SocketsPlugin plugin;  // Reference to SocketsPlugin for notifying JS
 | 
					    private SocketsPlugin plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Sockets(SocketsPlugin plugin) {
 | 
					    public Sockets(SocketsPlugin plugin) {
 | 
				
			||||||
        this.plugin = plugin;  // Pass plugin reference for message forwarding
 | 
					        this.plugin = plugin;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public SocketHandler create(String id) {
 | 
					    public SocketHandler create(String id) {
 | 
				
			||||||
@ -19,10 +19,10 @@ public class Sockets implements SocketHandler.SocketDelegate {
 | 
				
			|||||||
        return socket;
 | 
					        return socket;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void connect(String id, String host, int port, boolean useTLS, boolean acceptInvalidCertificates) {
 | 
					    public void connect(String id, String host, int port, boolean useTLS, boolean acceptInvalidCertificates, String delimiter) {
 | 
				
			||||||
        SocketHandler socket = getSocketById(id);
 | 
					        SocketHandler socket = getSocketById(id);
 | 
				
			||||||
        if (socket != null) {
 | 
					        if (socket != null) {
 | 
				
			||||||
            socket.connect(host, port, useTLS, acceptInvalidCertificates);
 | 
					            socket.connect(host, port, useTLS, acceptInvalidCertificates, delimiter);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,9 +37,14 @@ public class Sockets implements SocketHandler.SocketDelegate {
 | 
				
			|||||||
        SocketHandler socket = getSocketById(id);
 | 
					        SocketHandler socket = getSocketById(id);
 | 
				
			||||||
        if (socket != null) {
 | 
					        if (socket != null) {
 | 
				
			||||||
            socket.disconnect();
 | 
					            socket.disconnect();
 | 
				
			||||||
 | 
					            sockets.remove(socket);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int getActiveSocketCount() {
 | 
				
			||||||
 | 
					        return sockets.size();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private SocketHandler getSocketById(String id) {
 | 
					    private SocketHandler getSocketById(String id) {
 | 
				
			||||||
        for (SocketHandler socket : sockets) {
 | 
					        for (SocketHandler socket : sockets) {
 | 
				
			||||||
            if (socket.getId().equals(id)) {
 | 
					            if (socket.getId().equals(id)) {
 | 
				
			||||||
@ -49,19 +54,15 @@ public class Sockets implements SocketHandler.SocketDelegate {
 | 
				
			|||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle state changes (connected, disconnected)
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onStateChanged(String socketId, String state) {
 | 
					    public void onStateChanged(String socketId, String state) {
 | 
				
			||||||
        Log.d("Sockets", "Socket state changed: " + state);
 | 
					        Log.d("Sockets", "Socket state changed: " + state);
 | 
				
			||||||
        // Call notifyStateListeners in SocketsPlugin
 | 
					 | 
				
			||||||
        plugin.notifyStateListeners("state", socketId, state);
 | 
					        plugin.notifyStateListeners("state", socketId, state);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle incoming messages
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void onMessageReceived(String socketId, String message) {
 | 
					    public void onMessageReceived(String socketId, String message) {
 | 
				
			||||||
        Log.d("Sockets", "Socket message received: " + message);
 | 
					        Log.d("Sockets", "Socket message received: " + message);
 | 
				
			||||||
        // Call notifyMessageListeners in SocketsPlugin
 | 
					        plugin.notifyMessageListeners(socketId, message);
 | 
				
			||||||
        plugin.notifyMessageListeners(socketId, message);  // Notify JS about the received message
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,5 +1,7 @@
 | 
				
			|||||||
package software.eskimo.capacitor.sockets;
 | 
					package software.eskimo.capacitor.sockets;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.app.ActivityManager;
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
import android.content.Intent;
 | 
					import android.content.Intent;
 | 
				
			||||||
import android.util.Log;
 | 
					import android.util.Log;
 | 
				
			||||||
import com.getcapacitor.JSObject;
 | 
					import com.getcapacitor.JSObject;
 | 
				
			||||||
@ -11,7 +13,7 @@ import com.getcapacitor.PluginMethod;
 | 
				
			|||||||
@CapacitorPlugin(name = "Sockets")
 | 
					@CapacitorPlugin(name = "Sockets")
 | 
				
			||||||
public class SocketsPlugin extends Plugin {
 | 
					public class SocketsPlugin extends Plugin {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Sockets implementation = new Sockets(this);  // Pass the plugin reference
 | 
					    private Sockets implementation = new Sockets(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @PluginMethod
 | 
					    @PluginMethod
 | 
				
			||||||
    public void create(PluginCall call) {
 | 
					    public void create(PluginCall call) {
 | 
				
			||||||
@ -27,11 +29,11 @@ public class SocketsPlugin extends Plugin {
 | 
				
			|||||||
        int port = call.getInt("port", 0);
 | 
					        int port = call.getInt("port", 0);
 | 
				
			||||||
        boolean useTLS = call.getBoolean("useTLS", false);
 | 
					        boolean useTLS = call.getBoolean("useTLS", false);
 | 
				
			||||||
        boolean acceptInvalidCertificates = call.getBoolean("acceptInvalidCertificates", false);
 | 
					        boolean acceptInvalidCertificates = call.getBoolean("acceptInvalidCertificates", false);
 | 
				
			||||||
 | 
					        String delimiter = call.getString("delimiter", "\r\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Start the foreground service to keep the socket connection alive in the background
 | 
					 | 
				
			||||||
        startSocketForegroundService();
 | 
					        startSocketForegroundService();
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        implementation.connect(id, host, port, useTLS, acceptInvalidCertificates);
 | 
					        implementation.connect(id, host, port, useTLS, acceptInvalidCertificates, delimiter);
 | 
				
			||||||
        call.resolve();
 | 
					        call.resolve();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,10 +51,29 @@ public class SocketsPlugin extends Plugin {
 | 
				
			|||||||
        String id = call.getString("id", "");
 | 
					        String id = call.getString("id", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        implementation.disconnect(id);
 | 
					        implementation.disconnect(id);
 | 
				
			||||||
 | 
					        if (implementation.getActiveSocketCount() == 0) {
 | 
				
			||||||
 | 
					            stopSocketForegroundService();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        call.resolve();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @PluginMethod
 | 
				
			||||||
 | 
					    public void setNotificationText(PluginCall call) {
 | 
				
			||||||
 | 
					        String notificationText = call.getString("notificationText", "Maintaining connection");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        Intent intent = new Intent(getContext(), SocketForegroundService.class);
 | 
				
			||||||
 | 
					        intent.setAction("software.eskimo.capacitor.sockets.UPDATE_NOTIFICATION");
 | 
				
			||||||
 | 
					        intent.putExtra("notificationText", notificationText);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
 | 
				
			||||||
 | 
					            getContext().startForegroundService(intent);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            getContext().startService(intent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        call.resolve();
 | 
					        call.resolve();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Helper method for notifying JavaScript listeners about state changes
 | 
					 | 
				
			||||||
    public void notifyStateListeners(String event, String id, String state) {
 | 
					    public void notifyStateListeners(String event, String id, String state) {
 | 
				
			||||||
        JSObject data = new JSObject();
 | 
					        JSObject data = new JSObject();
 | 
				
			||||||
        data.put("id", id);
 | 
					        data.put("id", id);
 | 
				
			||||||
@ -70,9 +91,26 @@ public class SocketsPlugin extends Plugin {
 | 
				
			|||||||
        notifyListeners("message", data);
 | 
					        notifyListeners("message", data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Method to start the foreground service
 | 
					 | 
				
			||||||
    private void startSocketForegroundService() {
 | 
					    private void startSocketForegroundService() {
 | 
				
			||||||
 | 
					        if (!isServiceRunning(SocketForegroundService.class)) {
 | 
				
			||||||
 | 
					            Intent serviceIntent = new Intent(getContext(), SocketForegroundService.class);
 | 
				
			||||||
 | 
					            serviceIntent.putExtra("notificationText", "Maintaining connection");
 | 
				
			||||||
 | 
					            getContext().startForegroundService(serviceIntent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void stopSocketForegroundService() {
 | 
				
			||||||
        Intent serviceIntent = new Intent(getContext(), SocketForegroundService.class);
 | 
					        Intent serviceIntent = new Intent(getContext(), SocketForegroundService.class);
 | 
				
			||||||
        getContext().startForegroundService(serviceIntent);
 | 
					        getContext().stopService(serviceIntent);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private boolean isServiceRunning(Class<?> serviceClass) {
 | 
				
			||||||
 | 
					        ActivityManager manager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
 | 
				
			||||||
 | 
					        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
 | 
				
			||||||
 | 
					            if (serviceClass.getName().equals(service.service.getClassName())) {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "capacitor-sockets",
 | 
					  "name": "capacitor-sockets",
 | 
				
			||||||
  "version": "0.0.1",
 | 
					  "version": "0.0.4",
 | 
				
			||||||
  "description": "Sockets",
 | 
					  "description": "Sockets",
 | 
				
			||||||
  "main": "dist/plugin.cjs.js",
 | 
					  "main": "dist/plugin.cjs.js",
 | 
				
			||||||
  "module": "dist/esm/index.js",
 | 
					  "module": "dist/esm/index.js",
 | 
				
			||||||
 | 
				
			|||||||
@ -2,10 +2,11 @@ import { PluginListenerHandle } from "@capacitor/core";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export interface SocketsPlugin {
 | 
					export interface SocketsPlugin {
 | 
				
			||||||
  create(options: { id: string; }): Promise<void>;
 | 
					  create(options: { id: string; }): Promise<void>;
 | 
				
			||||||
  connect(options: { id: string; host: string; port: number, useTLS?: boolean, acceptInvalidCertificates?: boolean }): Promise<void>;
 | 
					  connect(options: { id: string; host: string; port: number, useTLS?: boolean, acceptInvalidCertificates?: boolean, delimiter?: string }): Promise<void>;
 | 
				
			||||||
  send(options: { id: string; message: string }): Promise<void>;
 | 
					  send(options: { id: string; message: string }): Promise<void>;
 | 
				
			||||||
  disconnect(options: { id: string }): Promise<void>;
 | 
					  disconnect(options: { id: string }): Promise<void>;
 | 
				
			||||||
  close(options: { id: string }): Promise<void>;
 | 
					  close(options: { id: string }): Promise<void>;
 | 
				
			||||||
 | 
					  setNotificationText(options: { notificationText: string }): Promise<void>;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  addListener(eventName: "state", listenerFunc: (message: { id: string; state: string }) => void): Promise<PluginListenerHandle>;
 | 
					  addListener(eventName: "state", listenerFunc: (message: { id: string; state: string }) => void): Promise<PluginListenerHandle>;
 | 
				
			||||||
  addListener(eventName: "message", listenerFunc: (message: { id: string; message: string }) => void): Promise<PluginListenerHandle>;
 | 
					  addListener(eventName: "message", listenerFunc: (message: { id: string; message: string }) => void): Promise<PluginListenerHandle>;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										170
									
								
								src/socket.ts
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								src/socket.ts
									
									
									
									
									
								
							@ -5,110 +5,112 @@ import mitt, { Emitter } from "mitt";
 | 
				
			|||||||
const Sockets = registerPlugin<SocketsPlugin>("Sockets");
 | 
					const Sockets = registerPlugin<SocketsPlugin>("Sockets");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SocketEvents = {
 | 
					type SocketEvents = {
 | 
				
			||||||
	message: string;
 | 
					    message: string;
 | 
				
			||||||
	state: string;
 | 
					    state: string;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SocketManager {
 | 
					class SocketManager {
 | 
				
			||||||
	private static instance: SocketManager;
 | 
					    private static instance: SocketManager;
 | 
				
			||||||
	private socketsMap: Map<string, Socket> = new Map();
 | 
					    private socketsMap: Map<string, Socket> = new Map();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private constructor() {
 | 
					    private constructor() {
 | 
				
			||||||
		this.addGlobalListeners();
 | 
					        this.addGlobalListeners();
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static getInstance() {
 | 
					    public static getInstance() {
 | 
				
			||||||
		if (!SocketManager.instance) {
 | 
					        if (!SocketManager.instance) {
 | 
				
			||||||
			SocketManager.instance = new SocketManager();
 | 
					            SocketManager.instance = new SocketManager();
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		return SocketManager.instance;
 | 
					        return SocketManager.instance;
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public registerSocket(socket: Socket) {
 | 
					    public registerSocket(socket: Socket) {
 | 
				
			||||||
		this.socketsMap.set(socket.id, socket);
 | 
					        this.socketsMap.set(socket.id, socket);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public unregisterSocket(socket: Socket) {
 | 
					    public unregisterSocket(socket: Socket) {
 | 
				
			||||||
		this.socketsMap.delete(socket.id);
 | 
					        this.socketsMap.delete(socket.id);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private addGlobalListeners() {
 | 
					    private addGlobalListeners() {
 | 
				
			||||||
		Sockets.addListener("state", (data) => {
 | 
					        Sockets.addListener("state", (data) => {
 | 
				
			||||||
			let socket = this.socketsMap.get(data.id);
 | 
					            let socket = this.socketsMap.get(data.id);
 | 
				
			||||||
			if (socket) {
 | 
					            if (socket) {
 | 
				
			||||||
				socket.didChangeState(data);
 | 
					                socket.didChangeState(data);
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Sockets.addListener("message", (data) => {
 | 
					        Sockets.addListener("message", (data) => {
 | 
				
			||||||
			let socket = this.socketsMap.get(data.id);
 | 
					            let socket = this.socketsMap.get(data.id);
 | 
				
			||||||
			if (socket) {
 | 
					            if (socket) {
 | 
				
			||||||
				socket.didReceiveMessage(data);
 | 
					                socket.didReceiveMessage(data);
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class Socket {
 | 
					export default class Socket {
 | 
				
			||||||
	id: string;
 | 
					    id: string;
 | 
				
			||||||
 | 
					    private emitter: Emitter<SocketEvents>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private emitter: Emitter<SocketEvents>;
 | 
					    constructor(config: { id: string }) {
 | 
				
			||||||
 | 
					        console.log(config);
 | 
				
			||||||
 | 
					        this.id = config.id;
 | 
				
			||||||
 | 
					        this.emitter = mitt<SocketEvents>();
 | 
				
			||||||
 | 
					        this.create();
 | 
				
			||||||
 | 
					        SocketManager.getInstance().registerSocket(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(config: { id: string }) {
 | 
					    on(event: keyof SocketEvents, handler: (data: any) => void) {
 | 
				
			||||||
		console.log(config);
 | 
					        this.emitter.on(event, handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.id = config.id;
 | 
					    async create() {
 | 
				
			||||||
 | 
					        await Sockets.create({
 | 
				
			||||||
 | 
					            id: this.id
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.emitter = mitt<SocketEvents>();
 | 
					    async connect(config: { host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean; delimiter?: string }) {
 | 
				
			||||||
 | 
					        await Sockets.connect({
 | 
				
			||||||
 | 
					            id: this.id,
 | 
				
			||||||
 | 
					            host: config.host,
 | 
				
			||||||
 | 
					            port: config.port,
 | 
				
			||||||
 | 
					            useTLS: config.useTLS ?? false,
 | 
				
			||||||
 | 
					            acceptInvalidCertificates: config.acceptInvalidCertificates ?? false,
 | 
				
			||||||
 | 
					            delimiter: config.delimiter ?? "\r\n"
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.create();
 | 
					    async disconnect() {
 | 
				
			||||||
 | 
					        await Sockets.disconnect({
 | 
				
			||||||
 | 
					            id: this.id
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SocketManager.getInstance().registerSocket(this);
 | 
					    async close() {
 | 
				
			||||||
	}
 | 
					        await this.disconnect();
 | 
				
			||||||
 | 
					        SocketManager.getInstance().unregisterSocket(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	on(event: keyof SocketEvents, handler: (data: any) => void) {
 | 
					    async send(message: string) {
 | 
				
			||||||
		this.emitter.on(event, handler);
 | 
					        await Sockets.send({
 | 
				
			||||||
	}
 | 
					            id: this.id,
 | 
				
			||||||
 | 
					            message: message
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	create() {
 | 
					    async setNotificationText(config: { notificationText: string }) {
 | 
				
			||||||
		Sockets.create({
 | 
					        await Sockets.setNotificationText({
 | 
				
			||||||
			id: this.id
 | 
					            notificationText: config.notificationText
 | 
				
			||||||
		});
 | 
					        });
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	connect(config: { host: string; port: number; useTLS?: boolean; acceptInvalidCertificates?: boolean }) {
 | 
					    didChangeState(data: { state: string }) {
 | 
				
			||||||
		Sockets.connect({
 | 
					        this.emitter.emit("state", data.state);
 | 
				
			||||||
			id: this.id,
 | 
					    }
 | 
				
			||||||
			host: config.host,
 | 
					 | 
				
			||||||
			port: config.port,
 | 
					 | 
				
			||||||
			useTLS: config.useTLS ?? false,
 | 
					 | 
				
			||||||
			acceptInvalidCertificates: config.acceptInvalidCertificates ?? false
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	disconnect() {
 | 
					    didReceiveMessage(data: { message: string }) {
 | 
				
			||||||
		Sockets.disconnect({
 | 
					        this.emitter.emit("message", data.message);
 | 
				
			||||||
			id: this.id
 | 
					    }
 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close() {
 | 
					 | 
				
			||||||
		this.disconnect();
 | 
					 | 
				
			||||||
		SocketManager.getInstance().unregisterSocket(this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	send(message: string) {
 | 
					 | 
				
			||||||
		Sockets.send({
 | 
					 | 
				
			||||||
			id: this.id,
 | 
					 | 
				
			||||||
			message: message
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	didChangeState(data: { state: string }) {
 | 
					 | 
				
			||||||
		this.emitter.emit("state", data.state);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	didReceiveMessage(data: { message: string }) {
 | 
					 | 
				
			||||||
		this.emitter.emit("message", data.message);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user