Quantcast
Channel: Active questions tagged react-native+android - Stack Overflow
Viewing all articles
Browse latest Browse all 28479

Socket IO with React Native and Headless JS, can't kill it

$
0
0

This is mi first post so I will try to show my problem in a clear way and I'm not an android developer with a basic kownledge of java.

I'm trying to run a socket IO client in my react-native app, as I inquire in order to achieve this I use Headless JS task to have this socket running in the background and even when the app is close, the user recieves a notification.

I have all the flow working well, but the only problem is that when I execute Background.stopService(), the websocket do not disconect but the persistance notification disappear.

index.js (where I register the task)

const MyHeadlessTask = async () => {
  const email = await AsyncStorage.getItem('email');

  if (!!email) {
    try {
      let socket = SocketIOClient('url', {
        transports: ['websocket'],
        query: `email=${email}`
      });

      etc...
    } catch (ex) {
      console.log('[MyHeadlessTask() ex] ', ex)
    }
  }
};

AppRegistry.registerHeadlessTask('Background', () => MyHeadlessTask);

BackgroundEventService.java

public class BackgroundEventService extends HeadlessJsTaskService {
  @Nullable
  protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
    Bundle extras = intent.getExtras();
    WritableMap data = extras != null ? Arguments.fromBundle(extras) : Arguments.createMap();

    return new HeadlessJsTaskConfig(
      "Background",
      data,
      5000,
      true
    );
  }
}

BackgroundModule.java

public class BackgroundModule extends ReactContextBaseJavaModule {

  public static final String REACT_CLASS = "Background";
  private static ReactApplicationContext reactContext;

  public BackgroundModule(@Nonnull ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
  }

  @Nonnull
  @Override
  public String getName() {
    return REACT_CLASS;
  }

  @ReactMethod
  public void startService() {
    this.reactContext.startService(new Intent(this.reactContext, BackgroundService.class));
  }

  @ReactMethod
  public void stopService() {
    this.reactContext.stopService(new Intent(this.reactContext, BackgroundService.class));
  }
}

BackgroundPackage.java

public class BackgroundPackage implements ReactPackage {

  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    return Arrays.<NativeModule>asList(
      new BackgroundModule(reactContext)
    );
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }
}

MainApplication.java (add package)

@Override
      protected List<ReactPackage> getPackages() {
        @SuppressWarnings("UnnecessaryLocalVariable")
        List<ReactPackage> packages = new PackageList(this).getPackages();
        // Packages that cannot be autolinked yet can be added manually here, for example:
        // packages.add(new MyReactNativePackage());
        packages.add(new BackgroundPackage());
        return packages;
      }

and this are the two ways that I writed BackgroundService.javafirst one

public class BackgroundService extends Service {

  private static final int SERVICE_NOTIFICATION_ID = 12345;
  private static final String CHANNEL_ID = "BACKGROUND";

  private Handler handler = new Handler();
  private Runnable runnableCode = new Runnable() {
    @Override
    public void run() {
      Context context = getApplicationContext();
      Intent myIntent = new Intent(context, BackgroundEventService.class);
      context.startService(myIntent);
      HeadlessJsTaskService.acquireWakeLockNow(context);
      //handler.postDelayed(this, 2000);
    }
  };
  private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      int importance = NotificationManager.IMPORTANCE_DEFAULT;
      NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "BACKGROUND", importance);
      channel.setDescription("CHANEL DESCRIPTION");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(channel);
    }
  }

  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public void onCreate() {
    super.onCreate();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    this.handler.removeCallbacks(this.runnableCode);
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    this.handler.post(this.runnableCode);
    createNotificationChannel();
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
      .setContentTitle("Safe Home")
      .setSmallIcon(R.mipmap.ic_launcher)
      .setContentIntent(contentIntent)
      .setOngoing(true)
      .setPriority(NotificationCompat.PRIORITY_MIN)
      .setVisibility(Notification.VISIBILITY_SECRET)
      .build();
    startForeground(SERVICE_NOTIFICATION_ID, notification);
    return START_STICKY;
  }

}

second one

public class BackgroundService extends Service {

  private static final int SERVICE_NOTIFICATION_ID = 12345;
  private static final String CHANNEL_ID = "BACKGROUND";
  private volatile boolean running = true;

  private Thread thread;
  private Runnable runnableCode = new Runnable() {
    @Override
    public void run() {
      if (running) {
        Context context = getApplicationContext();
        Intent myIntent = new Intent(context, BackgroundEventService.class);
        context.startService(myIntent);
        HeadlessJsTaskService.acquireWakeLockNow(context);
      } else {
        Context context = getApplicationContext();
        Intent myIntent = new Intent(context, BackgroundEventService.class);
        context.stopService(myIntent);
      }
    }
  };
  private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      int importance = NotificationManager.IMPORTANCE_DEFAULT;
      NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "BACKGROUND", importance);
      channel.setDescription("CHANEL DESCRIPTION");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(channel);
    }
  }

  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public void onCreate() {
    super.onCreate();
  }

  @Override
  public void onDestroy() {
    running = false;
    this.thread.interrupt();
    super.onDestroy();
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    this.thread = new Thread(this.runnableCode);
    this.thread.start();
    createNotificationChannel();
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
      .setContentTitle("Safe Home")
      .setSmallIcon(R.mipmap.ic_launcher)
      .setContentIntent(contentIntent)
      .setOngoing(true)
      .setPriority(NotificationCompat.PRIORITY_MIN)
      .setVisibility(Notification.VISIBILITY_SECRET)
      .build();
    startForeground(SERVICE_NOTIFICATION_ID, notification);
    return START_STICKY;
  }

}

This problem is giving me a headache, and I can't find a solution, I repeat everthing works well but it seems that the BackgroundEventService don't stop and the sockets still running, I try too many ways to stop the thread but nothing works for me. Maybe i'm using wrongs concepts or the is an error in my code...


Viewing all articles
Browse latest Browse all 28479

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>