I have Service for receive udp datagramm sockets
private void startServer(final UdpServerListener listener) {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
Looper myLooper = Looper.myLooper();
new HandlerThread("TcpServerThread") {
@Override
protected void onLooperPrepared() {
new Handler(getLooper()).post(() -> {
try {
byte[] data = new byte[8 * 1024];
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
//POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
} catch (IOException e) {
new Handler(myLooper).post(() -> listener.onServerStartFailed(e));
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
getLooper().quitSafely();
}
});
}
}.start();
}
So result data i post to listener via Binder
//POST MY DATA TO BINDER VIA HANDLE LOOPER AND LISTENER
new Handler(myLooper).post(() -> listener.onReceive(receiveData,datagramPacket.getAddress()));
See my listener:
@NonNull
private UdpServerService.UdpServerListener getUdpServerServiceListener() {
if (mUdpServerServiceListener == null) {
mUdpServerServiceListener = new UdpServerService.UdpServerListener() {
@Override
public void onReceive(final byte[] bytes, final InetAddress inetAddress) {
if (mSocketListener != null && mListenerLooper != null) {
//TRY TO RECEIVW MY DATA HERE
}
}
};
}
return mUdpServerServiceListener;
}
See my service connection class with binder
private class MyServiceConnection implements ServiceConnection {
UdpServerService.UdpServerBinder binder;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof UdpServerService.UdpServerBinder && mServerState == SERVER_STARTED) {
binder = (UdpServerService.UdpServerBinder) service;
binder.setListener(getUdpServerServiceListener());
binder.startServer();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//do something on disconnect
}
So, it all works greate but in old devices with version 5 and 6 Android.
But in my GalaxyS7, or in My Asus Zenfone 3
with Android 7 application freezes
and does not respond user touch until it is not stopped.
Maybe triggered some limiting mechanism, but I do not know anything about it.
maybe wrong build.gradle see it
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'idea'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
useLibrary 'org.apache.http.legacy'
}
buildTypes {
debug {
minifyEnabled false
debuggable true
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
packagingOptions{
exclude 'META-INF/rxjava.properties'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//gson parser
implementation 'com.google.code.gson:gson:2.8.0'
//kotlin
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// rxjava
implementation 'io.reactivex:rxjava:1.1.6'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.artemzin.rxjava:proguard-rules:1.1.0.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.8'
//help to avoid memory leaks
implementation 'com.badoo.mobile:android-weak-handler:1.0'
//guava for Android:
implementation 'com.google.guava:guava:23.6-android'
}
kotlin {
experimental {
coroutines "enable"
}
}
My solution is make this code simple, just work receive data in simple Thread, and post its data in the same thread:
void startServer() {
mStarted = true;
mWakeLock.acquire(10 * 60 * 1000L /*10 minutes*/);
new Thread(() -> {
try {
byte[] data = new byte[8 * 1024];//bucketful with fix size
InetAddress address = BnjUtils.getLocalIpAddress();
DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
mServerSocket = new DatagramSocket(0, address);
final InetAddress localAddress = ((InetSocketAddress) mServerSocket.getLocalSocketAddress()).getAddress();
final int port = mServerSocket.getLocalPort();
mListener.onServerCreated(localAddress, port);
while (mStarted) {
try {
mServerSocket.receive(datagramPacket); // blocks until something is received
/*
* Send bytes to app module.
*/
byte[] receiveData = new byte[datagramPacket.getLength()];
System.arraycopy(datagramPacket.getData(), datagramPacket.getOffset(), receiveData, 0, datagramPacket.getLength());
mListener.onReceive(receiveData, datagramPacket.getAddress());
} catch (IOException e) {
mListener.onServerStartFailed(e);
}
}
} catch (SocketException e) {
Log.e(mTag, "Socket Exception");
} finally {
if (mServerSocket != null && !mServerSocket.isClosed()) {
mServerSocket.close();
}
}
}).start();
}
So now, works without freeze.