sccn / liblsl

C++ lsl library for multi-modal time-synched data transmission over the local network
Other
107 stars 63 forks source link

Stream not found (Android) #204

Open VladimirR46 opened 8 months ago

VladimirR46 commented 8 months ago

Hello everyone!!!

I have created an application to show visual stimuli for Android platform on QT. When starting the application, I call:

std::shared_ptr<lsl::stream_outlet> m_outlet;
...
//Start function
lsl::stream_info info("NeuroStim-Events", "Events", 1, lsl::IRREGULAR_RATE, lsl::cf_int32, "7643562-7455141");
m_outlet.reset(new lsl::stream_outlet(info));

When I try to start recording a stream from Android using LabRecorder I get an error image

However, if I click yes, I soon get the following message in the console: image All data is recorded correctly. As it seems to me.)) If you hit the update button periodically (in LabRecorder UI), the stream is sometimes online and sometimes offline. I am using a Samsung Tab S7 tablet (Android 12). It and the PC are connected to the same WiFi network. I tested on another similar tablet and another PC. The problem is repeated(.

But when I build this application for Windows everything works fine!

VladimirR46 commented 8 months ago

I tried turning set(LSL_DEBUGLOG ON) But I get an error image

tstenner commented 8 months ago

Android has some problems with multicasting, especially on the emulator.

I'm a bit swamped right now, but I have bumped the SDK versions for the android build and updated the included loguru library (that finally includes my fixes for pthread based thread names). Android builds with LSL_DEBUGLOG=ON, maybe that helps already.

VladimirR46 commented 8 months ago

Thank you very much! I was able to compile with set(LSL_DEBUGLOG ON). But for that I needed to install Android API version 33.

VladimirR46 commented 8 months ago

@tstenner Hello!

After upgrading loguru library I am unable to build my Windows application using mingw. image

Also about the problem on Android. I don't use the simulator. And I don't get any error messages. But the stream still appears in LabRecorder and then disappears when I click the refresh button.

I added share.h and the program compiled successfully. But I still have some warnings. image

VladimirR46 commented 8 months ago

I think I've solved my problem!

By default, receiving UDP Multicast packets from Android is disabled. Even if you join a multicast group after binding to the correct address and port, no data arrives when you know it is being sent.

The reason is explained below: https://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html

To make it work, please perform the following steps:

Add the following permissions to the Android Manifest:

android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE

Create a file -> MulticastLocker.java

package org.qtproject;

import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.util.Log;
import org.qtproject.qt.android.bindings.QtApplication;

public class MulticastLocker extends Activity
{    
private static WifiManager.MulticastLock lock = null;    
public static void lockMulticast(Context context)
    {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        if(wifiManager != null){
            lock = wifiManager.createMulticastLock("Log_Tag");
            lock.acquire();
            Log.d(QtApplication.QtTAG, "The installation was a success!");
        }
    }
}

Done! Now before creating lsl::stream_outlet we just need to call the lockMulticast function from C++, for this I use QJniObject.

QJniObject::callStaticMethod<void>("org/qtproject/MulticastLocker", "lockMulticast", QNativeInterface::QAndroidApplication::context());

I also built LabRecorder for Android and it works too and writes all streams to an xdf file. =) Thank you all!

I'd like to recommend that you check out this solution. And maybe add a description in: https://labstreaminglayer.readthedocs.io/info/network-connectivity.html

VladimirR46 commented 8 months ago

But I have one more question. Why do I see localhost in LabRecorder? I am running the stream from an external Android device. image

pmaanen commented 7 months ago

But I have one more question. Why do I see localhost in LabRecorder? I am running the stream from an external Android device. image

The bracketed string is the 'hostname' field of the stream info, set by the sender when the stream info object gets bound to an outlet. I do not know where the sender takes the hostname from, but my guess is that Android phones always use 'localhost' as hostname, as I see the same behaviour on my Android apps.